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