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;
+}
openSUSE Build Service is sponsored by