File vlock-2.2.3-use-unix2_chkpwd.diff of Package vlock
Subject: add the possibility to use external unix2_chkpwd program
to authenticate
Author: Stefan Seyfried <seife+obs@b1-systems.com>
This adds the configure option "--enable-unix2_chkpwd" which uses external
/sbin/unix2_chkpwd from pam-modules package to authenticate the user.
The benefit is that vlock-main does not need sgid shadow to be able to read
the crypted password, because this all is handled by unix2_chkpwd
Index: b/Makefile
===================================================================
--- a/Makefile
+++ b/Makefile
@@ -98,10 +98,11 @@ override CFLAGS += -Isrc
vlock-main: vlock-main.o prompt.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-unix2_chkpwd.o: auth-unix2_chkpwd.c prompt.h auth.h
prompt.o: prompt.c prompt.h
vlock-main.o: vlock-main.c auth.h prompt.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
Index: b/configure
===================================================================
--- a/configure
+++ b/configure
@@ -76,14 +76,14 @@ enable_feature() {
ENABLE_PLUGINS="$2"
;;
root-password)
ENABLE_ROOT_PASSWORD="$2"
;;
- pam|shadow)
+ pam|shadow|unix2_chkpwd)
if [ "$2" = "yes" ] ; then
if [ -n "$auth_method" ] && [ "$auth_method" != "$1" ] ; then
- fatal_error "pam and shadow authentication are mutually exclusive"
+ fatal_error "pam, shadow and unix2_chkpwd authentication are mutually exclusive"
fi
AUTH_METHOD="$1"
else
fatal_error "cannot disable authentication"
fi
Index: b/src/auth-unix2_chkpwd.c
===================================================================
--- /dev/null
+++ b/src/auth-unix2_chkpwd.c
@@ -0,0 +1,107 @@
+/* auth-unix2_chkpwd.c -- authentification routine for vlock,
+ * the VT locking program for linux
+ * using external unix2_chkpwd binary
+ *
+ * This code is copyright (C) 2014 Stefan Seyfried, based on auth-shadow
+ * which is copyright (C) 2007 Frank Benkstein, and is free
+ * software which is freely distributable under the terms of the
+ * GNU General Public License version 2, included as the file COPYING in this
+ * distribution. It is NOT public domain software, and any
+ * redistribution not permitted by the GNU General Public License is
+ * expressly forbidden without prior written permission from
+ * the author.
+ *
+ */
+
+/* for crypt() */
+#define _XOPEN_SOURCE
+
+#ifndef __FreeBSD__
+/* for asprintf() */
+#define _GNU_SOURCE
+#endif
+
+#include <stdbool.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <pwd.h>
+#include <errno.h>
+#include "auth.h"
+#include "prompt.h"
+
+bool auth(const char *user, struct timespec *timeout)
+{
+ char *pwd = NULL;
+ char *msg;
+ struct passwd *pw = NULL;
+ int pfd[2], status;
+ pid_t pid;
+ int result = false;
+
+ /* format the prompt */
+ if (asprintf(&msg, "%s's Password: ", user) < 0)
+ return false;
+
+ pw = getpwnam(user);
+ if (! pw)
+ goto out;
+
+ if ((pwd = prompt_echo_off(msg, timeout)) == NULL)
+ goto out;
+
+ if (pipe(pfd) < 0) {
+ perror("vlock: pipe() failed");
+ goto out;
+ }
+
+ if ((pid = fork()) < 0) {
+ perror("vlock: fork() failed");
+ close(pfd[0]);
+ close(pfd[1]);
+ goto out;
+ }
+
+ if (pid == 0) {
+ close(pfd[1]);
+ if (pfd[0] != 0)
+ dup2(pfd[0], 0);
+
+ /* Helper is invoked as helper service-name [user] */
+ // printf("calling '/sbin/unix2_chkpwd vlock %s'\n", pw->pw_name);
+ execlp("/sbin/unix2_chkpwd", "/sbin/unix2_chkpwd", "vlock", pw->pw_name, NULL);
+ /* we should not come here! */
+ perror("vlock: execlp(/sbin/unix2_chkpwd)");
+ exit(1);
+ }
+
+ close(pfd[0]);
+ /* Write out password to helper process */
+ write(pfd[1], pwd, strlen(pwd));
+ close(pfd[1]);
+
+ while (waitpid(pid, &status, 0) < 0) {
+ if (errno == EINTR)
+ continue;
+ perror("vlock: waitpid() failed");
+ goto out;
+ }
+
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+ fprintf(stderr, "vlock: Authentication error\n"); /* no sleep needed, unix2_chkpwd already does that */
+ else
+ result = true;
+
+out:
+ /* free the password, free(NULL) is ok */
+ free(pwd);
+
+ /* free the prompt */
+ free(msg);
+
+ return result;
+}