Hi there :)

Here's first results of my efforts.

pam_fprint now supports user identification (i.e. you do not need to enter a 
username to login, it will automatically detects one)

=========================================
It's an alpha version, so I recommend use it only for testing!
=========================================

Unfornatelly, patch for libfprint required 
(0001-Added-function-to-update-storage-path.patch) . To collect fingerprints 
from all users I need to reset base_storage path for libfprint, so I've added 
such functionality. I don't like this solution, so any suggestions/other 
solutions are welcome ;) 

For now pam_fprint collects fingerprints from ~/.fprint for each user listed 
in /etc/fprint, so you must create this file and fill it with usernames you 
need. 

Known limitations/bugs:

- You should have unique fingerprints enrolled for each account. Later 
pam_fprint_enroll will ensure that fingerprint is unique.
- Identification supported only for imaging devices
- I don't know applications except pamtest that supports usernameless auth
- You need to create /etc/fprint file by hands

agetty doesn't support username-less auth.
No graphical login manager supports identification for the moment. I'll create 
a patch for kdm next week.

Regards
Vasily
From 152e55b9b0088bdf5701b9de1c308982ac49c2c2 Mon Sep 17 00:00:00 2001
From: Vasily Khoruzhick <[EMAIL PROTECTED]>
Date: Sun, 17 Feb 2008 18:53:08 +0200
Subject: [PATCH] Added function to update storage path


Signed-off-by: Vasily Khoruzhick <[EMAIL PROTECTED]>
---
 libfprint/data.c   |    9 +++++++++
 libfprint/fprint.h |    1 +
 2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/libfprint/data.c b/libfprint/data.c
index 2027e9c..33eb0eb 100644
--- a/libfprint/data.c
+++ b/libfprint/data.c
@@ -113,6 +113,15 @@ struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length)
 }
 
 /** \ingroup print_data
+ * Update a path to storage, used by fp_print_data_* functions
+ */
+API_EXPORTED void fp_print_data_update_storage_path(void)
+{
+	g_free(base_store);
+	base_store = NULL;
+}
+
+/** \ingroup print_data
  * Convert a stored print into a unified representation inside a data buffer.
  * You can then store this data buffer in any way that suits you, and load
  * it back at some later time using fp_print_data_from_data().
diff --git a/libfprint/fprint.h b/libfprint/fprint.h
index 2b85584..ff1f675 100644
--- a/libfprint/fprint.h
+++ b/libfprint/fprint.h
@@ -225,6 +225,7 @@ static inline int fp_identify_finger(struct fp_dev *dev,
 }
 
 /* Data handling */
+void fp_print_data_update_storage_path(void);
 int fp_print_data_load(struct fp_dev *dev, enum fp_finger finger,
 	struct fp_print_data **data);
 int fp_print_data_from_dscv_print(struct fp_dscv_print *print,
-- 
1.5.4

From 3877543fcef46e1dce9fcae89157871a6d144ca9 Mon Sep 17 00:00:00 2001
From: Vasily Khoruzhick <[EMAIL PROTECTED]>
Date: Fri, 15 Feb 2008 15:48:50 +0200
Subject: [PATCH] Use fp_identify_finger instead of verify


Signed-off-by: Vasily Khoruzhick <[EMAIL PROTECTED]>
---
 src/pam_fprint.c |   91 ++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 61 insertions(+), 30 deletions(-)

diff --git a/src/pam_fprint.c b/src/pam_fprint.c
index 847d2f0..3e7e7d9 100644
--- a/src/pam_fprint.c
+++ b/src/pam_fprint.c
@@ -70,6 +70,7 @@ static int send_err_msg(pam_handle_t *pamh, char *msg)
 	return pc->conv(1, &msgp, &resp, pc->appdata_ptr);
 }
 
+/*
 static const char *fingerstr(enum fp_finger finger)
 {
 	const char *names[] = {
@@ -88,42 +89,73 @@ static const char *fingerstr(enum fp_finger finger)
 		return "UNKNOWN";
 	return names[finger];
 }
+*/
 
-static int find_dev_and_print(struct fp_dscv_dev **ddevs,
-	struct fp_dscv_print **prints, struct fp_dscv_dev **_ddev,
-	struct fp_dscv_print **_print)
+static struct fp_print_data **find_dev_and_prints(struct fp_dscv_dev **ddevs,
+	struct fp_dscv_print **prints, struct fp_dscv_dev **_ddev)
 {
-	int i = 0;
+	int i = 0, j = 0, err;
 	struct fp_dscv_print *print;
-	struct fp_dscv_dev *ddev;
+	struct fp_dscv_dev *ddev = NULL;
+	uint16_t driver_id, driver_id_cur;
+	size_t prints_count = 0;
+	struct fp_print_data **gallery;
 
+	/* TODO: add device selection */
 	while (print = prints[i++]) {
-		ddev = fp_dscv_dev_for_dscv_print(ddevs, print);
-		if (ddev) {
+		if (!ddev) {
+			ddev = fp_dscv_dev_for_dscv_print(ddevs, print);
+			driver_id = fp_dscv_print_get_driver_id(print);
 			*_ddev = ddev;
-			*_print = print;
-			return 0;
+		}
+		if (ddev)
+		{
+		    driver_id_cur = fp_dscv_print_get_driver_id(print);
+		    if (driver_id_cur == driver_id) {
+			    prints_count++;
+		    }
+		}
+	}
+	
+	if (prints_count == 0) {
+	    return NULL;
+	}
+	
+	gallery = malloc(sizeof(*gallery) * (prints_count + 1));
+	gallery[prints_count] = NULL;
+	
+	i = 0, j = 0;
+	while (print = prints[i++]) {
+		driver_id_cur = fp_dscv_print_get_driver_id(print);
+		if (driver_id_cur == driver_id) {
+			err = fp_print_data_from_dscv_print(print, & (gallery[j]));
+			if (err != 0) {
+			    gallery[j] = NULL;
+			    break;
+			}
+			j++;
 		}
 	}
-	return 1;
+	
+	return gallery;
 }
 
-static int do_verify(pam_handle_t *pamh, struct fp_dev *dev,
-	struct fp_print_data *data, enum fp_finger finger)
+static int do_identify(pam_handle_t *pamh, struct fp_dev *dev,
+	struct fp_print_data **gallery)
 {
 	int max_tries = 5;
+	size_t offset;
 	const char *driver_name = fp_driver_get_full_name(fp_dev_get_driver(dev));
-	const char *fstr = fingerstr(finger);
-
+	
 	do {
 		int r;
 		char msg[128];
 
-		snprintf(msg, sizeof(msg), "Scan %s finger on %s", fstr, driver_name);
+		snprintf(msg, sizeof(msg), "Scan finger on %s", driver_name);
 		msg[sizeof(msg) - 1] = 0;
 		send_info_msg(pamh, msg);
 
-		r = fp_verify_finger(dev, data);
+		r = fp_identify_finger(dev, gallery, &offset);
 		if (r < 0) {
 			snprintf(msg, sizeof(msg), "Fingerprint verification error %d", r);
 			msg[sizeof(msg) - 1] = 0;
@@ -164,8 +196,7 @@ static int do_auth(pam_handle_t *pamh)
 	struct fp_dscv_dev *ddev;
 	struct fp_dscv_print *print;
 	struct fp_dev *dev;
-	struct fp_print_data *data;
-	enum fp_finger finger;
+	struct fp_print_data **gallery, **gallery_iter;
 
 	r = fp_init();
 	if (r < 0)
@@ -180,9 +211,9 @@ static int do_auth(pam_handle_t *pamh)
 		fp_dscv_devs_free(ddevs);
 		return PAM_AUTHINFO_UNAVAIL;
 	}
-
-	r = find_dev_and_print(ddevs, prints, &ddev, &print);
-	if (r) {
+	
+	gallery = find_dev_and_prints(ddevs, prints, &ddev);
+	if (!gallery || gallery[0] == NULL) {
 		fp_dscv_prints_free(prints);
 		fp_dscv_devs_free(ddevs);
 		send_info_msg(pamh, "Could not locate any suitable fingerprints "
@@ -197,17 +228,17 @@ static int do_auth(pam_handle_t *pamh)
 		return PAM_AUTHINFO_UNAVAIL;
 	}
 
-	finger = fp_dscv_print_get_finger(print);
-
-	r = fp_print_data_from_dscv_print(print, &data);
 	fp_dscv_prints_free(prints);
-	if (r) {
-		fp_dev_close(dev);
-		return PAM_AUTHINFO_UNAVAIL;
-	}
 
-	r = do_verify(pamh, dev, data, finger);
-	fp_print_data_free(data);
+	r = do_identify(pamh, dev, gallery);
+	
+	gallery_iter = gallery;
+	while (*gallery_iter)
+	{
+	    fp_print_data_free(*gallery_iter);
+	    gallery_iter++;
+	}
+	free(gallery);
 	fp_dev_close(dev);
 	return r;
 }
-- 
1.5.4

From 6d0b5805a708633e9727ece96c61aa790d62b718 Mon Sep 17 00:00:00 2001
From: Vasily Khoruzhick <[EMAIL PROTECTED]>
Date: Fri, 15 Feb 2008 19:30:27 +0200
Subject: [PATCH] Regression for devices that unsupport identification fixed


Signed-off-by: Vasily Khoruzhick <[EMAIL PROTECTED]>
---
 src/pam_fprint.c |   56 +++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 41 insertions(+), 15 deletions(-)

diff --git a/src/pam_fprint.c b/src/pam_fprint.c
index 3e7e7d9..24fc104 100644
--- a/src/pam_fprint.c
+++ b/src/pam_fprint.c
@@ -70,7 +70,7 @@ static int send_err_msg(pam_handle_t *pamh, char *msg)
 	return pc->conv(1, &msgp, &resp, pc->appdata_ptr);
 }
 
-/*
+
 static const char *fingerstr(enum fp_finger finger)
 {
 	const char *names[] = {
@@ -89,10 +89,10 @@ static const char *fingerstr(enum fp_finger finger)
 		return "UNKNOWN";
 	return names[finger];
 }
-*/
+
 
 static struct fp_print_data **find_dev_and_prints(struct fp_dscv_dev **ddevs,
-	struct fp_dscv_print **prints, struct fp_dscv_dev **_ddev)
+	struct fp_dscv_print **prints, struct fp_dscv_dev **_ddev, enum fp_finger **fingers)
 {
 	int i = 0, j = 0, err;
 	struct fp_dscv_print *print;
@@ -122,7 +122,15 @@ static struct fp_print_data **find_dev_and_prints(struct fp_dscv_dev **ddevs,
 	}
 	
 	gallery = malloc(sizeof(*gallery) * (prints_count + 1));
+	if (gallery == NULL) {
+	    return NULL;
+	}
 	gallery[prints_count] = NULL;
+	*fingers = malloc(sizeof(*fingers) * (prints_count));
+	if (*fingers == NULL) {
+	    free(gallery);
+	    return NULL;
+	}
 	
 	i = 0, j = 0;
 	while (print = prints[i++]) {
@@ -133,6 +141,7 @@ static struct fp_print_data **find_dev_and_prints(struct fp_dscv_dev **ddevs,
 			    gallery[j] = NULL;
 			    break;
 			}
+			(*fingers)[j] = fp_dscv_print_get_finger(print);
 			j++;
 		}
 	}
@@ -141,21 +150,31 @@ static struct fp_print_data **find_dev_and_prints(struct fp_dscv_dev **ddevs,
 }
 
 static int do_identify(pam_handle_t *pamh, struct fp_dev *dev,
-	struct fp_print_data **gallery)
+	struct fp_print_data **gallery, enum fp_finger *fingers)
 {
 	int max_tries = 5;
 	size_t offset;
 	const char *driver_name = fp_driver_get_full_name(fp_dev_get_driver(dev));
+	const char *fstr = fingerstr(fingers[0]);
 	
 	do {
 		int r;
 		char msg[128];
 
-		snprintf(msg, sizeof(msg), "Scan finger on %s", driver_name);
-		msg[sizeof(msg) - 1] = 0;
-		send_info_msg(pamh, msg);
-
-		r = fp_identify_finger(dev, gallery, &offset);
+		
+		if (fp_dev_supports_identification(dev)) {
+		    snprintf(msg, sizeof(msg), "Scan finger on %s", driver_name);
+		    msg[sizeof(msg) - 1] = 0;
+		    send_info_msg(pamh, msg);
+		    r = fp_identify_finger(dev, gallery, &offset);
+		    
+		}
+		else {
+		    snprintf(msg, sizeof(msg), "Scan %s finger on %s", fstr, driver_name);
+		    msg[sizeof(msg) - 1] = 0;
+		    send_info_msg(pamh, msg);
+		    r = fp_verify_finger(dev, gallery[0]);
+		}
 		if (r < 0) {
 			snprintf(msg, sizeof(msg), "Fingerprint verification error %d", r);
 			msg[sizeof(msg) - 1] = 0;
@@ -197,6 +216,7 @@ static int do_auth(pam_handle_t *pamh)
 	struct fp_dscv_print *print;
 	struct fp_dev *dev;
 	struct fp_print_data **gallery, **gallery_iter;
+	enum fp_finger *fingers;
 
 	r = fp_init();
 	if (r < 0)
@@ -212,8 +232,8 @@ static int do_auth(pam_handle_t *pamh)
 		return PAM_AUTHINFO_UNAVAIL;
 	}
 	
-	gallery = find_dev_and_prints(ddevs, prints, &ddev);
-	if (!gallery || gallery[0] == NULL) {
+	gallery = find_dev_and_prints(ddevs, prints, &ddev, &fingers);
+	if (!gallery) {
 		fp_dscv_prints_free(prints);
 		fp_dscv_devs_free(ddevs);
 		send_info_msg(pamh, "Could not locate any suitable fingerprints "
@@ -223,14 +243,19 @@ static int do_auth(pam_handle_t *pamh)
 
 	dev = fp_dev_open(ddev);
 	fp_dscv_devs_free(ddevs);
+	fp_dscv_prints_free(prints);
 	if (!dev) {
-		fp_dscv_prints_free(prints);
+		gallery_iter = gallery;
+		while (*gallery_iter) {
+		    fp_print_data_free(*gallery_iter);
+		    gallery_iter++;
+		}
+		free(gallery);
+		free(fingers);	
 		return PAM_AUTHINFO_UNAVAIL;
 	}
 
-	fp_dscv_prints_free(prints);
-
-	r = do_identify(pamh, dev, gallery);
+	r = do_identify(pamh, dev, gallery, fingers);
 	
 	gallery_iter = gallery;
 	while (*gallery_iter)
@@ -239,6 +264,7 @@ static int do_auth(pam_handle_t *pamh)
 	    gallery_iter++;
 	}
 	free(gallery);
+	free(fingers);
 	fp_dev_close(dev);
 	return r;
 }
-- 
1.5.4

From ff512294a5293859fa99834ab83746d0c1d33b7e Mon Sep 17 00:00:00 2001
From: Vasily Khoruzhick <[EMAIL PROTECTED]>
Date: Sun, 17 Feb 2008 20:09:31 +0200
Subject: [PATCH] Identification support added


Signed-off-by: Vasily Khoruzhick <[EMAIL PROTECTED]>
---
 src/Makefile.am         |    4 +-
 src/pam_fprint.c        |  250 ++++++++++++++++--------------------
 src/pam_fprint_common.c |  327 +++++++++++++++++++++++++++++++++++++++++++++++
 src/pam_fprint_common.h |   72 +++++++++++
 src/pam_fprint_enroll.c |   22 +---
 5 files changed, 514 insertions(+), 161 deletions(-)
 create mode 100644 src/pam_fprint_common.c
 create mode 100644 src/pam_fprint_common.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 1877ddc..2e124a7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,7 +3,7 @@ bin_PROGRAMS = pam_fprint_enroll
 pammod_PROGRAMS = pam_fprint.so
 pammoddir=/lib/security
 
-pam_fprint_so_SOURCES = pam_fprint.c
+pam_fprint_so_SOURCES = pam_fprint.c pam_fprint_common.c pam_fprint_common.h
 pam_fprint_so_CFLAGS = -fPIC $(FPRINT_CFLAGS)
 pam_fprint_so_LDFLAGS = -shared
 pam_fprint_so_LDADD = $(PAM_LIBS) $(FPRINT_LIBS)
@@ -11,6 +11,6 @@ pam_fprint_so_LDADD = $(PAM_LIBS) $(FPRINT_LIBS)
 pamtest_SOURCES = pamtest.c
 pamtest_LDADD = $(PAM_LIBS) -lpam_misc
 
-pam_fprint_enroll_SOURCES = pam_fprint_enroll.c
+pam_fprint_enroll_SOURCES = pam_fprint_enroll.c pam_fprint_common.c pam_fprint_common.h
 pam_fprint_enroll_LDADD = $(FPRINT_LIBS)
 pam_fprint_enroll_CFLAGS = $(FPRINT_CFLAGS)
diff --git a/src/pam_fprint.c b/src/pam_fprint.c
index 24fc104..b648971 100644
--- a/src/pam_fprint.c
+++ b/src/pam_fprint.c
@@ -1,6 +1,7 @@
 /*
  * pam_fprint: PAM module for fingerprint authentication through libfprint
  * Copyright (C) 2007 Daniel Drake <[EMAIL PROTECTED]>
+ * Copyright (C) 2007-2008 Vasily Khoruzhick <[EMAIL PROTECTED]>
  * 
  * 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
@@ -23,7 +24,8 @@
 #include <pwd.h>
 #include <string.h>
 
-#include <fprint.h>
+#include <libfprint/fprint.h>
+#include "pam_fprint_common.h"
 
 #define PAM_SM_AUTH
 #include <security/pam_modules.h>
@@ -70,107 +72,24 @@ static int send_err_msg(pam_handle_t *pamh, char *msg)
 	return pc->conv(1, &msgp, &resp, pc->appdata_ptr);
 }
 
-
-static const char *fingerstr(enum fp_finger finger)
-{
-	const char *names[] = {
-		[LEFT_THUMB] = "left thumb",
-		[LEFT_INDEX] = "left index",
-		[LEFT_MIDDLE] = "left middle",
-		[LEFT_RING] = "left ring",
-		[LEFT_LITTLE] = "left little",
-		[RIGHT_THUMB] = "right thumb",
-		[RIGHT_INDEX] = "right index",
-		[RIGHT_MIDDLE] = "right middle",
-		[RIGHT_RING] = "right ring",
-		[RIGHT_LITTLE] = "right little",
-	};
-	if (finger < LEFT_THUMB || finger > RIGHT_LITTLE)
-		return "UNKNOWN";
-	return names[finger];
-}
-
-
-static struct fp_print_data **find_dev_and_prints(struct fp_dscv_dev **ddevs,
-	struct fp_dscv_print **prints, struct fp_dscv_dev **_ddev, enum fp_finger **fingers)
-{
-	int i = 0, j = 0, err;
-	struct fp_dscv_print *print;
-	struct fp_dscv_dev *ddev = NULL;
-	uint16_t driver_id, driver_id_cur;
-	size_t prints_count = 0;
-	struct fp_print_data **gallery;
-
-	/* TODO: add device selection */
-	while (print = prints[i++]) {
-		if (!ddev) {
-			ddev = fp_dscv_dev_for_dscv_print(ddevs, print);
-			driver_id = fp_dscv_print_get_driver_id(print);
-			*_ddev = ddev;
-		}
-		if (ddev)
-		{
-		    driver_id_cur = fp_dscv_print_get_driver_id(print);
-		    if (driver_id_cur == driver_id) {
-			    prints_count++;
-		    }
-		}
-	}
-	
-	if (prints_count == 0) {
-	    return NULL;
-	}
-	
-	gallery = malloc(sizeof(*gallery) * (prints_count + 1));
-	if (gallery == NULL) {
-	    return NULL;
-	}
-	gallery[prints_count] = NULL;
-	*fingers = malloc(sizeof(*fingers) * (prints_count));
-	if (*fingers == NULL) {
-	    free(gallery);
-	    return NULL;
-	}
-	
-	i = 0, j = 0;
-	while (print = prints[i++]) {
-		driver_id_cur = fp_dscv_print_get_driver_id(print);
-		if (driver_id_cur == driver_id) {
-			err = fp_print_data_from_dscv_print(print, & (gallery[j]));
-			if (err != 0) {
-			    gallery[j] = NULL;
-			    break;
-			}
-			(*fingers)[j] = fp_dscv_print_get_finger(print);
-			j++;
-		}
-	}
-	
-	return gallery;
-}
-
 static int do_identify(pam_handle_t *pamh, struct fp_dev *dev,
-	struct fp_print_data **gallery, enum fp_finger *fingers)
+                       struct fp_print_data **gallery, size_t *offset)
 {
 	int max_tries = 5;
-	size_t offset;
 	const char *driver_name = fp_driver_get_full_name(fp_dev_get_driver(dev));
-	const char *fstr = fingerstr(fingers[0]);
 	
 	do {
 		int r;
 		char msg[128];
-
 		
 		if (fp_dev_supports_identification(dev)) {
 		    snprintf(msg, sizeof(msg), "Scan finger on %s", driver_name);
 		    msg[sizeof(msg) - 1] = 0;
 		    send_info_msg(pamh, msg);
-		    r = fp_identify_finger(dev, gallery, &offset);
-		    
+		    r = fp_identify_finger(dev, gallery, offset);
 		}
 		else {
-		    snprintf(msg, sizeof(msg), "Scan %s finger on %s", fstr, driver_name);
+		    snprintf(msg, sizeof(msg), "Scan finger on %s", driver_name);
 		    msg[sizeof(msg) - 1] = 0;
 		    send_info_msg(pamh, msg);
 		    r = fp_verify_finger(dev, gallery[0]);
@@ -207,65 +126,131 @@ static int do_identify(pam_handle_t *pamh, struct fp_dev *dev,
 	return PAM_AUTHINFO_UNAVAIL;
 }
 
-static int do_auth(pam_handle_t *pamh)
+static int do_auth(pam_handle_t *pamh, int ask_username)
 {
 	int r;
 	struct fp_dscv_dev **ddevs;
-	struct fp_dscv_print **prints;
 	struct fp_dscv_dev *ddev;
-	struct fp_dscv_print *print;
 	struct fp_dev *dev;
 	struct fp_print_data **gallery, **gallery_iter;
-	enum fp_finger *fingers;
+	int *gallery_users = NULL;
+	const char *username;
+	char **usernames, **usernames_iter;
+	size_t offset;
+	int have_user = 0;
 
 	r = fp_init();
 	if (r < 0)
 		return PAM_AUTHINFO_UNAVAIL;
 
 	ddevs = fp_discover_devs();
-	if (!ddevs)
+	if (!ddevs) {
+		fp_exit();
+		send_info_msg(pamh, "Failed to discover devices.");
 		return PAM_AUTHINFO_UNAVAIL;
+	}
 
-	prints = fp_discover_prints();
-	if (!prints) {
+	r = find_device_by_num(0, ddevs, &ddev);
+	if (r != 0) {
 		fp_dscv_devs_free(ddevs);
+		fp_exit();
+		send_info_msg(pamh, "Hardware device was not found.");
 		return PAM_AUTHINFO_UNAVAIL;
 	}
+		
+	pam_get_item(pamh, PAM_USER, (const void **)(const void *) &username);
+	if (username != NULL) have_user = 1;
 	
-	gallery = find_dev_and_prints(ddevs, prints, &ddev, &fingers);
-	if (!gallery) {
-		fp_dscv_prints_free(prints);
-		fp_dscv_devs_free(ddevs);
-		send_info_msg(pamh, "Could not locate any suitable fingerprints "
-			"matched with available hardware.");
-		return PAM_AUTHINFO_UNAVAIL;
+	if (ask_username || have_user) {
+		if (!have_user)
+		{
+			r = pam_get_user(pamh, &username, NULL);
+			if (r != PAM_SUCCESS) {
+				fp_dscv_devs_free(ddevs);
+				fp_exit();
+				return PAM_AUTHINFO_UNAVAIL;
+			}
+		}
+		r = build_gallery_for_username(username, ddev, &gallery);
+		if (r < 0) {
+			fp_dscv_devs_free(ddevs);
+			fp_exit();
+			send_info_msg(pamh, "Could not locate any suitable fingerprints "
+			              "matched with available hardware.");
+			return PAM_AUTHINFO_UNAVAIL;
+		}
+	}
+	else {
+		/*printf("Getting usernames...\n");*/
+		r = get_usernames_to_identify(&usernames);
+		/*printf("got usernames:\n");
+		usernames_iter = usernames;
+		while (*usernames_iter) {
+			printf("%s\n", *usernames_iter);
+			usernames_iter++;
+		}*/
+		if (r < 0) {
+			fp_dscv_devs_free(ddevs);
+			fp_exit();
+			send_info_msg(pamh, "Could not locate any suitable fingerprints "
+			              "matched with available hardware.");
+			return PAM_AUTHINFO_UNAVAIL;
+		}
+		r = build_gallery_for_usernames(usernames, ddev, &gallery, &gallery_users);
+		/*gallery_iter = gallery;
+		printf("got gallery, r=%d:\n", r);
+		while (*gallery_iter)
+		{
+			printf("%p\n", *gallery_iter);
+			gallery_iter++;
+		}
+		*/
+		if (r < 0) {
+			free_usernames(usernames);
+			fp_dscv_devs_free(ddevs);
+			fp_exit();
+			send_info_msg(pamh, "Could not locate any suitable fingerprints "
+			              "matched with available hardware.");
+			return PAM_AUTHINFO_UNAVAIL;
+		}
 	}
 
 	dev = fp_dev_open(ddev);
 	fp_dscv_devs_free(ddevs);
-	fp_dscv_prints_free(prints);
-	if (!dev) {
-		gallery_iter = gallery;
-		while (*gallery_iter) {
-		    fp_print_data_free(*gallery_iter);
-		    gallery_iter++;
-		}
-		free(gallery);
-		free(fingers);	
+	
+	if (dev == NULL) {
+		free_gallery(gallery);
+		free(gallery_users);
+		if (ask_username == 0 && have_user == 0) free_usernames(usernames);
 		return PAM_AUTHINFO_UNAVAIL;
 	}
-
-	r = do_identify(pamh, dev, gallery, fingers);
 	
-	gallery_iter = gallery;
-	while (*gallery_iter)
-	{
-	    fp_print_data_free(*gallery_iter);
-	    gallery_iter++;
+	if (!fp_dev_supports_identification(dev) && !ask_username) {
+		send_info_msg(pamh, "Can't perform identification on this device.");
+		free_gallery(gallery);
+		free(gallery_users);
+		if (ask_username == 0 && have_user == 0) free_usernames(usernames);
+		return PAM_AUTHINFO_UNAVAIL;
 	}
-	free(gallery);
-	free(fingers);
+	
+	r = do_identify(pamh, dev, gallery, &offset);
+	/*printf("Identify done, offset: %d\n", offset);*/
+	
+	if (!ask_username && !have_user && r == PAM_SUCCESS) {
+		int pam_ret;
+		char msg[128];
+		snprintf(msg, sizeof(msg), "fprint: identified user %s", usernames[gallery_users[offset]]);
+		send_info_msg(pamh, msg);
+		pam_ret  = pam_set_item(pamh, PAM_USER, usernames[gallery_users[offset]]);
+		if (pam_ret != PAM_SUCCESS) r = PAM_AUTHINFO_UNAVAIL; 
+	}
+	
+	free_gallery(gallery);
+	free(gallery_users);
+	if (ask_username == 0 && have_user == 0) free_usernames(usernames);
 	fp_dev_close(dev);
+	fp_exit();
+	
 	return r;
 }
 
@@ -275,36 +260,17 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
 	const char *rhost = NULL;
 	FILE *fd;
 	char buf[5];
-	const char *username;
-	char *homedir;
+	const char *username = NULL;
 	struct passwd *passwd;
 	int r;
-
+	int ask_username = 0;
+	
 	pam_get_item(pamh, PAM_RHOST, (const void **)(const void*) &rhost);
 	if (rhost != NULL && strlen(rhost) > 0) {
 		/* remote login (e.g. over SSH) */
 		return PAM_AUTHINFO_UNAVAIL;
 	}
-
-	r = pam_get_user(pamh, &username, NULL);
-	if (r != PAM_SUCCESS)
-		return PAM_AUTHINFO_UNAVAIL;
-
-	passwd = getpwnam(username);
-	if (!passwd)
-		return PAM_AUTHINFO_UNAVAIL;
-
-	homedir = strdup(passwd->pw_dir);
-
-	/* a bit of a hack to make libfprint use the right home dir */
-	r = setenv("HOME", homedir, 1);
-	if (r < 0) {
-		free(homedir);
-		return PAM_AUTHINFO_UNAVAIL;
-	}
-
-	r = do_auth(pamh);
-	free(homedir);
+	r = do_auth(pamh, ask_username);
 	return r;
 }
 
diff --git a/src/pam_fprint_common.c b/src/pam_fprint_common.c
new file mode 100644
index 0000000..53de2fe
--- /dev/null
+++ b/src/pam_fprint_common.c
@@ -0,0 +1,327 @@
+/*
+ * pam_fprint_common: Common routines for enroll app and PAM module
+ * Copyright (C) 2008 Vasily Khoruzhick <[EMAIL PROTECTED]>
+ * 
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libfprint/fprint.h>
+#include "pam_fprint_common.h"
+
+#include <sys/types.h>
+#include <pwd.h>
+
+static const char *names[] = {
+		[LEFT_THUMB] = "left thumb",
+		[LEFT_INDEX] = "left index",
+		[LEFT_MIDDLE] = "left middle",
+		[LEFT_RING] = "left ring",
+		[LEFT_LITTLE] = "left little",
+		[RIGHT_THUMB] = "right thumb",
+		[RIGHT_INDEX] = "right index",
+		[RIGHT_MIDDLE] = "right middle",
+		[RIGHT_RING] = "right ring",
+		[RIGHT_LITTLE] = "right little",
+		[RIGHT_LITTLE + 1] = "UNKNOWN"
+};
+
+const char *fingerstr(enum fp_finger finger)
+{
+	
+	if (finger < LEFT_THUMB || finger > RIGHT_LITTLE)
+		return names[RIGHT_LITTLE + 1];
+	return names[finger];
+}
+
+/* 
+ * Returns NULL-terminated list of users to identify 
+ * usernames must be freed with free_usernames_to_identify()
+ * after perfoming necessary ops
+ */
+int get_usernames_to_identify(char ***_usernames)
+{
+	FILE *input;
+	int usernames_count = 0;
+	char **usernames;
+	
+	/* Assuming that username is lesser than 256 bytes */
+	char buf[256], *buf_iter;
+	
+	input = fopen(PAM_FPRINT_USERNAMES_FILE, "r");
+	if (input == NULL) 
+	{
+		return -1;
+	}
+	
+	usernames = malloc(sizeof(*usernames) * (usernames_count + 1));
+	if (usernames == NULL)
+	{
+		fclose(input);
+		return -1;
+	}
+	usernames[usernames_count] = NULL;
+	
+	while (!feof(input))
+	{
+		if (fgets(buf, 256, input) == NULL) break;
+		usernames_count++;
+		buf_iter = buf;
+		while (*buf_iter)
+		{
+			if (*buf_iter == 0x0a || *buf_iter == 0x0d) 
+			{
+				*buf_iter = 0;
+				break;
+			}
+			buf_iter++;
+		}
+		/* TODO: I don't like realloc, so it should be replaced with linked list
+		 * or something like this
+		 */
+		usernames = realloc(usernames, sizeof(*usernames) * (usernames_count + 1));
+		usernames[usernames_count] = NULL;
+		usernames[usernames_count - 1] = strdup(buf);
+	}
+	
+	fclose(input);
+	*_usernames = usernames;
+	return 0;
+}
+
+/*  
+ * Frees list allocated by get_usernames_to_identify()
+ */
+void free_usernames(char **usernames)
+{
+	char **usernames_iter = usernames;
+	if (!usernames) return;
+	
+	while (*usernames_iter)
+	{
+		free(*usernames_iter);
+		usernames_iter++;
+	}
+	free(usernames);
+}
+
+/* 
+ * Selects device by device number
+ */
+int find_device_by_num(int num, struct fp_dscv_dev **devs, struct fp_dscv_dev **_ddev)
+{
+	struct fp_dscv_dev **devs_iter;
+	
+	devs_iter = devs;
+	if (devs == NULL)
+	{
+		return -1;
+	}
+	
+	/* Checking if requested device exists */
+	while (num-- && (*devs_iter != NULL) )
+	{
+		devs_iter++;
+	}
+	
+	if (*devs_iter == NULL)
+	{
+		return -1;
+	}
+	
+	*_ddev = *devs_iter;	
+	return 0;
+}
+
+/* 
+ * Selects first device with driver_id == id
+ */
+int find_device_by_driver_id(uint16_t id, struct fp_dscv_dev **devs, struct fp_dscv_dev **_ddev)
+{
+	struct fp_dscv_dev **devs_iter;
+	
+	devs_iter = devs;
+	if (devs == NULL)
+	{
+		return -1;
+	}
+	
+	/* Checking if requested device exists */
+	while (*devs_iter != NULL)
+	{
+		if (fp_dscv_dev_get_driver_id(*devs_iter) == id) break;
+		devs_iter++;
+	}
+	
+	if (*devs_iter == NULL)
+	{
+		return -1;
+	}
+	
+	*_ddev = *devs_iter;	
+	return 0;
+}
+
+/*
+ * Builds gallery for list of usernames
+ * Must be freed after performing necessary ops with
+ * free_gallery
+ */
+int build_gallery_for_usernames(char **usernames, struct fp_dscv_dev *ddev,
+                                struct fp_print_data ***_gallery, int **_gallery_users)
+{
+	struct passwd *passwd;
+	char *homedir;
+	int  current_username = 0;
+	struct fp_print_data **gallery = NULL, **gallery_tmp;
+	struct fp_dscv_print **prints, **prints_iter;
+	int *gallery_users = NULL, *gallery_users_tmp;
+	int prints_count = 0, r = 0;
+	uint16_t driver_id = fp_dscv_dev_get_driver_id(ddev);
+	
+	gallery = malloc(sizeof(*gallery) * (prints_count + 1) );
+	if (gallery == NULL) return -1;
+	gallery[prints_count] = NULL;
+	gallery_users = malloc(sizeof(*gallery_users) * (prints_count + 1));
+	if (gallery_users == NULL)
+	{
+		free(gallery);
+		return -1;
+	}
+	gallery_users[prints_count] = -1;
+	
+	while (usernames[current_username])
+	{
+		passwd = getpwnam(usernames[current_username]);
+		if (!passwd)
+			continue;
+		
+		homedir = strdup(passwd->pw_dir);
+		
+		/* a bit of a hack to make libfprint use the right home dir */
+		r = setenv("HOME", homedir, 1);
+		if (r < 0) {
+			free(homedir);
+			continue;
+		}
+		
+		/*printf("for user %s homedir %s...\n", usernames[current_username], homedir);*/
+		
+		
+		free(homedir);
+		
+		/* Hack to allow fprint use multiply HOMEs */
+		fp_print_data_update_storage_path();
+		
+		prints = prints_iter = fp_discover_prints();
+		if (prints == NULL) {
+			current_username++;
+			continue;
+		};
+		
+		
+		while (*prints_iter)
+		{
+			if (fp_dscv_print_get_driver_id(*prints_iter) == driver_id)
+			{
+				/*printf("found print\n");*/
+				prints_count++;
+				gallery_tmp = realloc(gallery, sizeof(*gallery) * (prints_count + 1));
+				if (gallery_tmp == NULL)
+				{
+					/* Well, at least part of gallery was built
+					 * we'll return that part, but with err = 1
+					 */
+					fp_dscv_prints_free(prints);
+					*_gallery = gallery;
+					*_gallery_users = gallery_users;
+					return 1;
+				}
+				gallery = gallery_tmp;
+				gallery[prints_count] = NULL;
+				r = fp_print_data_from_dscv_print(*prints_iter, &(gallery[prints_count - 1]));
+				if (r != 0)
+				{
+					/* Some error occured while retrieving print data
+					 * We'll return correct part of gallery
+					 */
+					fp_dscv_prints_free(prints);
+					*_gallery = gallery;
+					*_gallery_users = gallery_users;
+					return 1;
+				}
+				
+				gallery_users_tmp = realloc(gallery_users, sizeof(*gallery_users) * (prints_count + 1));
+				if (gallery_tmp == NULL)
+				{
+					/* Well, at least part of gallery was built correctly
+					 * we'll try to recover from error and return 
+					 * that part, but with err = 1
+					 */
+					fp_dscv_prints_free(prints);
+					fp_print_data_free(gallery[prints_count - 1]);
+					gallery[prints_count - 1] = NULL;
+					*_gallery = gallery;
+					*_gallery_users = gallery_users;
+					return 1;
+				}
+				gallery_users = gallery_users_tmp;
+				gallery_users[prints_count] = -1;
+				gallery_users[prints_count - 1] = current_username;
+			}
+			prints_iter++;
+		}
+		
+		fp_dscv_prints_free(prints);
+		current_username++;
+	}
+	
+	*_gallery = gallery;
+	*_gallery_users = gallery_users;
+	
+	return 0;
+}
+
+/*
+ * Builds gallery for single username
+ * Must be freed after performing necessary ops with
+ * free_gallery
+ */
+int build_gallery_for_username(const char *username, struct fp_dscv_dev *ddev, struct fp_print_data ***_gallery)
+{
+	int *gallery_users, res;
+	const char *usernames[] = { username, NULL };
+	
+	res = build_gallery_for_usernames((char **)usernames, ddev, _gallery, &gallery_users);
+	free (gallery_users);
+	
+	return res;
+}
+
+/*
+ * Frees gallery allocated by build_gallery_*()
+ */
+void free_gallery(struct fp_print_data **_gallery)
+{
+	struct fp_print_data **gallery_iter = _gallery;
+	while (*gallery_iter)
+	{
+		fp_print_data_free(*gallery_iter);
+		gallery_iter++;
+	}
+	free (_gallery);
+}
diff --git a/src/pam_fprint_common.h b/src/pam_fprint_common.h
new file mode 100644
index 0000000..b6d7dce
--- /dev/null
+++ b/src/pam_fprint_common.h
@@ -0,0 +1,72 @@
+/*
+ * pam_fprint_common: Common routines for enroll app and PAM module
+ * Copyright (C) 2008 Vasily Khoruzhick <[EMAIL PROTECTED]>
+ * 
+ * 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.
+ */
+
+#ifndef __PAM_FPRINT_COMMON_H__
+#define __PAM_FPRINT_COMMON_H__
+
+/* File containing usernames to identify */
+#ifndef PAM_FPRINT_USERNAMES_FILE
+#define PAM_FPRINT_USERNAMES_FILE "/etc/fprint"
+#endif
+
+const char *fingerstr(enum fp_finger finger);
+
+/* 
+ * Returns NULL-terminated list of users to identify 
+ * usernames must be freed with free_usernames_to_identify()
+ * after perfoming necessary ops
+ */
+int get_usernames_to_identify(char ***usernames);
+
+/*  
+ * Frees list allocated by get_usernames_to_identify()
+ */
+void free_usernames(char **usernames);
+
+/* 
+ * Selects device by device number
+ */
+int find_device_by_num(int num, struct fp_dscv_dev **devs, struct fp_dscv_dev **_ddev);
+
+/* 
+ * Selects first device with driver_id == id
+ */
+int find_device_by_driver_id(uint16_t id, struct fp_dscv_dev **devs, struct fp_dscv_dev **_ddev);
+
+/*
+ * Builds gallery for list of usernames
+ * Must be freed after performing necessary ops with
+ * free_gallery
+ */
+int build_gallery_for_usernames(char **usernames, struct fp_dscv_dev *ddev, 
+                                struct fp_print_data ***_gallery, int **_gallery_users);
+
+/*
+ * Builds gallery for single username
+ * Must be freed after performing necessary ops with
+ * free_gallery
+ */
+int build_gallery_for_username(const char *username, struct fp_dscv_dev *ddev, struct fp_print_data ***_gallery);
+
+/*
+ * Frees gallery allocated by build_gallery_*()
+ */
+void free_gallery(struct fp_print_data **_gallery);
+
+#endif
diff --git a/src/pam_fprint_enroll.c b/src/pam_fprint_enroll.c
index fa04fcc..46e4ed6 100644
--- a/src/pam_fprint_enroll.c
+++ b/src/pam_fprint_enroll.c
@@ -27,19 +27,7 @@
 #include <getopt.h>
 
 #include <libfprint/fprint.h>
-
-static const char *finger_names[] = {
-	[LEFT_THUMB] = "Left Thumb",
-	[LEFT_INDEX] = "Left Index Finger",
-	[LEFT_MIDDLE] = "Left Middle Finger",
-	[LEFT_RING] = "Left Ring Finger",
-	[LEFT_LITTLE] = "Left Little Finger",
-	[RIGHT_THUMB] = "Right Thumb",
-	[RIGHT_INDEX] = "Right Index Finger",
-	[RIGHT_MIDDLE] = "Right Middle Finger",
-	[RIGHT_RING] = "Right Ring Finger",
-	[RIGHT_LITTLE] = "Right Little Finger",
-};
+#include "pam_fprint_common.h"
 
 
 static struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs)
@@ -63,7 +51,7 @@ static struct fp_print_data *enroll(struct fp_dev *dev, enum fp_finger finger)
 	int r;	
 
 	printf("You will need to successfully scan your %s %d times to "
-		"complete the process.\n", finger_names[finger], fp_dev_get_nr_enroll_stages(dev));
+	       "complete the process.\n", fingerstr(finger), fp_dev_get_nr_enroll_stages(dev));
 
 	do {
 		sleep(1);
@@ -138,10 +126,10 @@ int main(int argc, char *argv[])
 			/* Printing usage */
 			printf("Usage: %s options\n", argv[0]);
 			printf("	-h	--help			Display this usage information.\n"
-			   "	-f	--enroll-finger index	Enroll finger with index.\n\n");
+				"	-f	--enroll-finger index	Enroll finger with index.\n\n");
 			printf("	Valid indexes are:\n");
 			for (i = LEFT_THUMB; i <= RIGHT_LITTLE; i++) {
-				printf("	%d - %s\n", i, finger_names[i]);
+				printf("	%d - %s\n", i, fingerstr(finger));
 			}
 			exit(1);
 			   
@@ -152,7 +140,7 @@ int main(int argc, char *argv[])
 				printf("%s: Invalid finger index.\n", argv[0]);
 				printf("%s: Valid indexes are:\n", argv[0]);
 				for (i = LEFT_THUMB; i <= RIGHT_LITTLE; i++) {
-					printf("%s: %d - %s\n", argv[0], i, finger_names[i]);
+					printf("%s: %d - %s\n", argv[0], i, fingerstr(finger));
 				}
 				exit(1);
 			}
-- 
1.5.4

_______________________________________________
fprint mailing list
[email protected]
http://lists.reactivated.net/mailman/listinfo/fprint

Reply via email to