--- vlock-2.2.3/Makefile	2011-09-18 17:22:35.000000000 +0200
+++ vlock-2.2.3/Makefile	2011-12-23 19:41:47.000000000 +0100
@@ -96,12 +96,13 @@
 
 override CFLAGS += -Isrc
 
-vlock-main: vlock-main.o prompt.o auth-$(AUTH_METHOD).o console_switch.o util.o
+vlock-main: vlock-main.o prompt.o fprint.o auth-$(AUTH_METHOD).o console_switch.o util.o
 
 auth-pam.o: auth-pam.c prompt.h auth.h
-auth-shadow.o: auth-shadow.c prompt.h auth.h
+auth-shadow.o: auth-shadow.c prompt.h auth.h fprint.h
+fprint.o: fprint.c fprint.h
 prompt.o: prompt.c prompt.h
-vlock-main.o: vlock-main.c auth.h prompt.h util.h
+vlock-main.o: vlock-main.c auth.h prompt.h fprint.h util.h
 plugins.o: plugins.c tsort.h plugin.h plugins.h list.h util.h
 module.o : override CFLAGS += -DVLOCK_MODULE_DIR="\"$(MODULEDIR)\""
 module.o: module.c plugin.h list.h util.h
@@ -123,7 +124,7 @@
 endif
 
 ifeq ($(AUTH_METHOD),shadow)
-vlock-main : override LDLIBS += $(CRYPT_LIB)
+vlock-main : override LDLIBS += $(CRYPT_LIB) -lfprint
 endif
 
 ifeq ($(ENABLE_PLUGINS),yes)
--- vlock-2.2.3/src/auth-shadow.c	2011-09-18 17:22:35.000000000 +0200
+++ vlock-2.2.3/src/auth-shadow.c	2011-12-23 19:48:04.000000000 +0100
@@ -30,6 +30,7 @@
 #include <shadow.h>
 
 #include "auth.h"
+#include "fprint.h"
 #include "prompt.h"
 
 bool auth(const char *user, struct timespec *timeout)
@@ -39,31 +40,49 @@
   char *msg;
   struct spwd *spw;
   int result = false;
+  bool fpallow = false;
+  bool fpavail = false;
 
-  /* format the prompt */
-  if (asprintf(&msg, "%s's Password: ", user) < 0)
-    return false;
-
-  if ((pwd = prompt_echo_off(msg, timeout)) == NULL)
-    goto out_pwd;
-
-  /* get the shadow password */
-  if ((spw = getspnam(user)) == NULL)
-    goto out_shadow;
-
-  /* hash the password */
-  if ((cryptpw = crypt(pwd, spw->sp_pwdp)) == NULL) {
-    perror("vlock: crypt()");
-    goto out_shadow;
+  if (fpallow = fprint_allowed(user)) {
+    if (fpavail = fprint_load()) {
+      fprintf(stderr, "%s's Fingerprint: ", user);
+      result = fprint_auth();
+    } else
+      fputs("vlock: Fingerprint authentication is not available,"
+          " falling back to password authentication\n", stderr);
+    fprint_unload();
   }
 
-  result = (strcmp(cryptpw, spw->sp_pwdp) == 0);
+  if (!fpavail || !fpallow) {
+    /* format the prompt */
+    if (asprintf(&msg, "%s's Password: ", user) < 0)
+      return false;
+
+    if ((pwd = prompt_echo_off(msg, timeout)) == NULL)
+      goto out_pwd;
+
+    /* get the shadow password */
+    if ((spw = getspnam(user)) == NULL)
+      goto out_shadow;
+
+    /* hash the password */
+    if ((cryptpw = crypt(pwd, spw->sp_pwdp)) == NULL) {
+      perror("vlock: crypt()");
+      goto out_shadow;
+    }
+
+    result = (strcmp(cryptpw, spw->sp_pwdp) == 0);
+  }
 
   if (!result) {
     sleep(1);
     fprintf(stderr, "vlock: Authentication error\n");
   }
 
+  if (fpavail && fpallow)
+    /* no need to clean up */
+    return result;
+
 out_shadow:
   /* deallocate shadow resources */
   endspent();
--- vlock-2.2.3/src/fprint.c	1970-01-01 01:00:00.000000000 +0100
+++ vlock-2.2.3/src/fprint.c	2011-12-23 19:41:47.000000000 +0100
@@ -0,0 +1,109 @@
+#include <sys/types.h>
+#include <grp.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "fprint.h"
+
+static struct fp_print_data *data;
+static struct fp_dev        *handle;
+
+bool
+fprint_init(void)
+{
+	if (fp_init() != 0) {
+		fprintf(stderr, "couldn't initialize fprint\n");
+		return false;
+	}
+
+	return true;
+}
+
+void
+fprint_exit(void)
+{
+	fp_exit();
+}
+
+bool
+fprint_allowed(const char *user)
+{
+	struct group *grp = getgrnam("fpauth");
+
+	char **members = grp->gr_mem;
+	char  *member = NULL;
+
+	while (member = *members++)
+		if (strcmp(user, member) == 0)
+			return true;
+
+	return false;
+}
+
+bool
+fprint_load(void) {
+	struct fp_dscv_dev   **list = NULL;
+	struct fp_dscv_print **prints = NULL;
+
+	list = fp_discover_devs();
+	if (list != NULL && list[0] != NULL)
+		handle = fp_dev_open(list[0]);
+
+	/* list may also be NULL */
+	fp_dscv_devs_free(list);
+	list = NULL;
+
+	if (handle != NULL) {
+		prints = fp_discover_prints();
+		if (prints != NULL && prints[0] != NULL) {
+			(void)fp_print_data_from_dscv_print(prints[0], &data);
+
+			fp_dscv_prints_free(prints);
+			prints = NULL;
+		}
+	}
+
+	return data != NULL;
+}
+
+void
+fprint_unload(void)
+{
+	fp_print_data_free(data);
+	fp_dev_close(handle);
+	data = handle = NULL;
+}
+
+bool
+fprint_auth(void)
+{
+	enum fp_verify_result result = FP_VERIFY_NO_MATCH;
+
+	do {
+		result = fp_verify_finger(handle, data);
+		switch (result) {
+		case FP_VERIFY_RETRY:
+			fprintf(stderr, "try again\n");
+			break;
+		case FP_VERIFY_RETRY_TOO_SHORT:
+			fprintf(stderr, "try again, slowly\n");
+			break;
+		case FP_VERIFY_RETRY_CENTER_FINGER:
+			fprintf(stderr, "try again, "
+				"finger centered on sensor\n");
+			break;
+		case FP_VERIFY_RETRY_REMOVE_FINGER:
+			fprintf(stderr, "try again, "
+				"removing finger from sensor afterwards\n");
+			/* FALLTHROUGH */
+		default:
+			break;
+		}
+	} while (result != FP_VERIFY_MATCH
+	      && result != FP_VERIFY_NO_MATCH);
+
+	return result == FP_VERIFY_MATCH;
+}
--- vlock-2.2.3/src/fprint.h	1970-01-01 01:00:00.000000000 +0100
+++ vlock-2.2.3/src/fprint.h	2011-12-23 19:41:47.000000000 +0100
@@ -0,0 +1,18 @@
+#ifndef _FPRINT_H_
+#define _FPRINT_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <libfprint/fprint.h>
+
+bool fprint_init(void);
+void fprint_exit(void);
+
+bool fprint_allowed(const char *);
+
+bool fprint_load(void);
+bool fprint_auth(void);
+void fprint_unload(void);
+
+#endif  /* !_FPRINT_H_ */
--- vlock-2.2.3/src/vlock-main.c	2011-09-18 17:22:35.000000000 +0200
+++ vlock-2.2.3/src/vlock-main.c	2011-12-23 19:41:47.000000000 +0100
@@ -27,6 +27,7 @@
 #include "prompt.h"
 #include "auth.h"
 #include "console_switch.h"
+#include "fprint.h"
 #include "util.h"
 
 #ifdef USE_PLUGINS
@@ -257,7 +258,9 @@
   setup_terminal();
   ensure_atexit(restore_terminal);
 
+  fprint_init();
   auth_loop(username);
+  fprint_exit();
 
   free(username);
 
