summaryrefslogtreecommitdiffstats
path: root/driver/passwd-helper.c
diff options
context:
space:
mode:
authorSimon Rettberg2018-10-16 10:08:48 +0200
committerSimon Rettberg2018-10-16 10:08:48 +0200
commitd3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch)
treecbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /driver/passwd-helper.c
downloadxscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip
Original 5.40
Diffstat (limited to 'driver/passwd-helper.c')
-rw-r--r--driver/passwd-helper.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/driver/passwd-helper.c b/driver/passwd-helper.c
new file mode 100644
index 0000000..a3a6b92
--- /dev/null
+++ b/driver/passwd-helper.c
@@ -0,0 +1,162 @@
+/* passwd-helper.c --- verifying typed passwords with external helper program
+ * written by Olaf Kirch <okir@suse.de>
+ * xscreensaver, Copyright (c) 1993-2005 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+/* The idea here is to be able to run xscreensaver without any setuid bits.
+ * Password verification happens through an external program that you feed
+ * your password to on stdin. The external command is invoked with a user
+ * name argument.
+ *
+ * The external helper does whatever authentication is necessary. Currently,
+ * SuSE uses "unix2_chkpwd", which is a variation of "unix_chkpwd" from the
+ * PAM distribution.
+ *
+ * Normally, the password helper should just authenticate the calling user
+ * (i.e. based on the caller's real uid). This is in order to prevent
+ * brute-forcing passwords in a shadow environment. A less restrictive
+ * approach would be to allow verifying other passwords as well, but always
+ * with a 2 second delay or so. (Not sure what SuSE's "unix2_chkpwd"
+ * currently does.)
+ * -- Olaf Kirch <okir@suse.de>, 16-Dec-2003
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifndef NO_LOCKING /* whole file */
+
+#include <X11/Xlib.h> /* not used for much... */
+
+/* This file doesn't need the Xt headers, so stub these types out... */
+#undef XtPointer
+#define XtAppContext void*
+#define XrmDatabase void*
+#define XtIntervalId void*
+#define XtPointer void*
+#define Widget void*
+
+#include "xscreensaver.h"
+
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+
+#include <sys/wait.h>
+
+static int
+ext_run (const char *user, const char *typed_passwd, int verbose_p)
+{
+ int pfd[2], status;
+ pid_t pid;
+
+ if (pipe(pfd) < 0)
+ return 0;
+
+ if (verbose_p)
+ fprintf (stderr, "%s: ext_run (%s, %s)\n",
+ blurb(), PASSWD_HELPER_PROGRAM, user);
+
+ block_sigchld();
+
+ if ((pid = fork()) < 0) {
+ close(pfd[0]);
+ close(pfd[1]);
+ return 0;
+ }
+
+ if (pid == 0) {
+ close(pfd[1]);
+ if (pfd[0] != 0)
+ dup2(pfd[0], 0);
+
+ /* Helper is invoked as helper service-name [user] */
+ execlp(PASSWD_HELPER_PROGRAM, PASSWD_HELPER_PROGRAM, "xscreensaver", user, NULL);
+ if (verbose_p)
+ fprintf(stderr, "%s: %s\n", PASSWD_HELPER_PROGRAM,
+ strerror(errno));
+ exit(1);
+ }
+
+ close(pfd[0]);
+
+ /* Write out password to helper process */
+ if (!typed_passwd)
+ typed_passwd = "";
+ write(pfd[1], typed_passwd, strlen(typed_passwd));
+ close(pfd[1]);
+
+ while (waitpid(pid, &status, 0) < 0) {
+ if (errno == EINTR)
+ continue;
+ if (verbose_p)
+ fprintf(stderr, "%s: ext_run: waitpid failed: %s\n",
+ blurb(), strerror(errno));
+ unblock_sigchld();
+ return 0;
+ }
+
+ unblock_sigchld();
+
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+ return 0;
+ return 1;
+}
+
+
+
+/* This can be called at any time, and says whether the typed password
+ belongs to either the logged in user (real uid, not effective); or
+ to root.
+ */
+int
+ext_passwd_valid_p (const char *typed_passwd, int verbose_p)
+{
+ struct passwd *pw;
+ int res = 0;
+
+ if ((pw = getpwuid(getuid())) != NULL)
+ res = ext_run (pw->pw_name, typed_passwd, verbose_p);
+ endpwent();
+
+#ifdef ALLOW_ROOT_PASSWD
+ if (!res)
+ res = ext_run ("root", typed_passwd, verbose_p);
+#endif /* ALLOW_ROOT_PASSWD */
+
+ return res;
+}
+
+
+int
+ext_priv_init (int argc, char **argv, int verbose_p)
+{
+ /* Make sure the passwd helper exists */
+ if (access(PASSWD_HELPER_PROGRAM, X_OK) < 0) {
+ fprintf(stderr,
+ "%s: warning: %s does not exist.\n"
+ "%s: password authentication via "
+ "external helper will not work.\n",
+ blurb(), PASSWD_HELPER_PROGRAM, blurb());
+ return 0;
+ }
+ return 1;
+}
+
+#endif /* NO_LOCKING -- whole file */