summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am7
-rw-r--r--configure.ac25
-rw-r--r--helper/Makefile.am27
-rw-r--r--helper/helper_proto.c167
-rw-r--r--helper/helper_proto.h53
-rw-r--r--helper/pam-helper.c289
-rw-r--r--src/Makefile.am16
-rw-r--r--src/gs-auth-helper.c202
-rw-r--r--src/gs-auth-pam.c28
-rw-r--r--src/gs-auth-pam.h54
10 files changed, 733 insertions, 135 deletions
diff --git a/Makefile.am b/Makefile.am
index 7bc464b..eca9048 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,7 +10,12 @@ DISTCHECK_CONFIGURE_FLAGS = \
--enable-compile-warnings=no \
CFLAGS='-Wno-deprecated-declarations'
-SUBDIRS = \
+SUBDIRS =
+if BUILTIN_HELPER
+SUBDIRS += helper
+endif
+
+SUBDIRS += \
po \
src \
savers \
diff --git a/configure.ac b/configure.ac
index 65325cd..7c203ed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -816,30 +816,29 @@ fi
# all in xscreensaver itself; the external program just does auth.)
have_passwd_helper=no
-with_passwd_helper_req=unspecified
+builtin_helper=no
AC_ARG_WITH(passwd-helper,
[ --with-passwd-helper Include support for an external password
verification helper program.],
- [with_passwd_helper="$withval"; with_passwd_helper_req="$withval"],[with_passwd_helper=no])
+ [with_passwd_helper="$withval"],[with_passwd_helper=no])
# no HANDLE_X_PATH_ARG for this one
if test "$enable_locking" = no ; then
- with_passwd_helper_req=no
with_passwd_helper=no
+ builtin_helper=no
fi
case "$with_passwd_helper" in
""|no) : ;;
/*)
AC_DEFINE_UNQUOTED(PASSWD_HELPER_PROGRAM, "$with_passwd_helper", [Full pathname of password helper application])
+ builtin_helper=no
have_passwd_helper=yes;;
*)
echo "error: --with-passwd-helper needs full pathname of helper (not '$with_passwd_helper')." >&2
exit 1
esac
-AM_CONDITIONAL(HAVE_PASSWD_HELPER, test x$have_passwd_helper = xyes)
-AC_SUBST(HAVE_PASSWD_HELPER)
if test "$need_setuid" = yes -a "$have_pam" != yes ; then
NEED_SETUID=yes
@@ -863,7 +862,9 @@ if test x$enable_authentication_scheme = xpam -a x$have_pam = xno ; then
AC_MSG_ERROR(PAM support requested but not available)
fi
if test x$enable_authentication_scheme = xhelper -a x$have_passwd_helper = xno ; then
- AC_MSG_ERROR(Password helper support requested but not available)
+ builtin_helper=yes
+ have_passwd_helper=yes
+ AC_DEFINE_UNQUOTED(PASSWD_HELPER_PROGRAM, [PKGLIBEXECDIR "/mate-screensaver-pam-helper"], [Full pathname of password helper application])
fi
if test x$enable_authentication_scheme = xbsdauth -a x$have_bsdauth = xno ; then
AC_MSG_ERROR(bsd_auth(3) support requested but not available)
@@ -892,6 +893,9 @@ else
fi
AC_SUBST(AUTH_SCHEME)
+AM_CONDITIONAL(HAVE_PASSWD_HELPER, test x$have_passwd_helper = xyes)
+AM_CONDITIONAL(BUILTIN_HELPER, test x$builtin_helper = xyes)
+AC_SUBST(HAVE_PASSWD_HELPER)
dnl ---------------------------------------------------------------------------
dnl ConsoleKit
@@ -1001,6 +1005,14 @@ if test "x$have_libnotify" = "xyes"; then
fi
dnl ---------------------------------------------------------------------------
+dnl glib headers for pam-helper
+dnl ---------------------------------------------------------------------------
+
+PKG_CHECK_MODULES(PAM_HELPER,
+ glib-2.0 >= $GLIB_REQUIRED_VERSION)
+AC_SUBST(PAM_HELPER_CFLAGS)
+
+dnl ---------------------------------------------------------------------------
dnl Finish
dnl ---------------------------------------------------------------------------
@@ -1117,6 +1129,7 @@ data/images/cosmos/Makefile
savers/Makefile
doc/Makefile
doc/mate-screensaver.xml
+helper/Makefile
])
echo "
diff --git a/helper/Makefile.am b/helper/Makefile.am
new file mode 100644
index 0000000..7a0ab0a
--- /dev/null
+++ b/helper/Makefile.am
@@ -0,0 +1,27 @@
+## We require new-style dependency handling.
+AUTOMAKE_OPTIONS = 1.7
+
+noinst_LIBRARIES = libhelper-proto.a
+
+libhelper_proto_a_CFLAGS = \
+ $(PAM_HELPER_CFLAGS) \
+ -I$(top_srcdir)/src
+
+libhelper_proto_a_SOURCES = \
+ helper_proto.h \
+ helper_proto.c
+
+pkglibexec_PROGRAMS = mate-screensaver-pam-helper
+
+mate_screensaver_pam_helper_CFLAGS = \
+ $(PAM_HELPER_CFLAGS) \
+ -I$(top_srcdir)/src
+
+mate_screensaver_pam_helper_SOURCES = \
+ pam-helper.c
+
+mate_screensaver_pam_helper_LDADD = \
+ libhelper-proto.a
+
+mate_screensaver_pam_helper_LDFLAGS = \
+ $(AUTH_LIBS)
diff --git a/helper/helper_proto.c b/helper/helper_proto.c
new file mode 100644
index 0000000..3abe263
--- /dev/null
+++ b/helper/helper_proto.c
@@ -0,0 +1,167 @@
+/* Part of mate-screensaver.
+ *
+ * Copyright (c) 2019-2021 Paul Wolneykien <[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 St, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Provides functions for two-way communication between the screensaver
+ * and the helper program. The idea of helper program is to be able to
+ * run mate-screensaver-dialog without any setuid bits.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "helper_proto.h"
+
+static ssize_t
+read_all (int fd, void *buf, size_t count)
+{
+ ssize_t rd, t_rd = 0;
+
+ if (0 == count)
+ return 0;
+
+ while (t_rd < count)
+ {
+ rd = read (fd, buf + t_rd, count - t_rd);
+ if (0 == rd)
+ break;
+ if (rd < 0)
+ return rd;
+ t_rd += rd;
+ }
+
+ return t_rd;
+}
+
+ssize_t
+read_msg (int fd, char *buf, size_t length)
+{
+ size_t msg_len;
+ ssize_t rd;
+
+ rd = read_all (fd, &msg_len, sizeof msg_len);
+ if (rd < 0)
+ return HELPER_IO_ERR;
+ if (rd > 0 && rd != sizeof msg_len)
+ return HELPER_LENGTH_READ_ERR;
+
+ if (msg_len >= length)
+ return HELPER_TOO_LONG_ERR;
+
+ if (msg_len > 0)
+ {
+ rd = read_all (fd, buf, msg_len);
+ if (rd < 0)
+ return HELPER_IO_ERR;
+ if (rd != msg_len)
+ return HELPER_MSG_READ_ERR;
+ }
+ else
+ rd = 0;
+ buf[rd] = '\0';
+
+ return rd;
+}
+
+int
+read_prompt (int fd, char *buf, size_t *length)
+{
+ int msg_type, rd;
+
+ rd = read_all (fd, &msg_type, sizeof msg_type);
+ if (0 == rd)
+ return 0;
+ if (rd < 0)
+ return HELPER_IO_ERR;
+ if (rd > 0 && rd != sizeof msg_type)
+ return HELPER_TYPE_READ_ERR;
+
+ rd = read_msg (fd, buf, *length);
+ if (rd < 0)
+ return rd;
+
+ *length = rd;
+ return msg_type;
+}
+
+static ssize_t
+write_all (int fd, const void *buf, size_t count)
+{
+ ssize_t wt, t_wt = 0;
+
+ if (0 == count)
+ return 0;
+
+ while (t_wt < count)
+ {
+ wt = write (fd, buf + t_wt, count - t_wt);
+ if (0 == wt)
+ break;
+ if (wt < 0)
+ return wt;
+ t_wt += wt;
+ }
+
+ return t_wt;
+}
+
+ssize_t
+write_msg (int fd, const void *buf, size_t length)
+{
+ ssize_t wt;
+
+ wt = write_all (fd, &length, sizeof length);
+ if (wt < 0)
+ return HELPER_IO_ERR;
+ if (wt > 0 && wt != sizeof length)
+ return HELPER_LENGTH_WRITE_ERR;
+
+ if (length > 0)
+ {
+ wt = write_all (fd, buf, length);
+ if (wt < 0)
+ return HELPER_IO_ERR;
+ if (wt != length)
+ return HELPER_MSG_WRITE_ERR;
+ }
+ else
+ wt = 0;
+
+ return wt;
+}
+
+int
+write_prompt (int fd, int msg_type, const void *buf, size_t length)
+{
+ ssize_t wt;
+
+ wt = write_all (fd, &msg_type, sizeof msg_type);
+ if (wt < 0)
+ return HELPER_IO_ERR;
+ if (wt > 0 && wt != sizeof msg_type)
+ return HELPER_TYPE_WRITE_ERR;
+
+ wt = write_msg (fd, buf, length);
+
+ return wt;
+}
diff --git a/helper/helper_proto.h b/helper/helper_proto.h
new file mode 100644
index 0000000..b815b52
--- /dev/null
+++ b/helper/helper_proto.h
@@ -0,0 +1,53 @@
+/* Part of mate-screensaver.
+ *
+ * Copyright (c) 2019-2021 Paul Wolneykien <[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 St, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Provides functions for two-way communication between the screensaver
+ * and the helper program. The idea of helper program is to be able to
+ * run mate-screensaver-dialog without any setuid bits.
+ */
+
+#ifndef __HELPER_PROTO_H
+#define __HELPER_PROTO_H
+
+#include "config.h"
+
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#define HELPER_IO_ERR -1
+
+#define HELPER_LENGTH_READ_ERR -2
+#define HELPER_TOO_LONG_ERR -3
+#define HELPER_MSG_READ_ERR -4
+#define HELPER_TYPE_READ_ERR -5
+
+ssize_t read_msg (int fd, char *buf, size_t length);
+int read_prompt (int fd, char *buf, size_t *length);
+
+#define HELPER_LENGTH_WRITE_ERR -6
+#define HELPER_MSG_WRITE_ERR -7
+#define HELPER_TYPE_WRITE_ERR -8
+
+ssize_t write_msg (int fd, const void *buf, size_t length);
+int write_prompt (int fd, int msg_type, const void *buf, size_t length);
+
+#endif /* __HELPER_PROTO_H */
diff --git a/helper/pam-helper.c b/helper/pam-helper.c
new file mode 100644
index 0000000..c2bd837
--- /dev/null
+++ b/helper/pam-helper.c
@@ -0,0 +1,289 @@
+/* Part of mate-screensaver.
+ *
+ * Copyright (C) 2002 SuSE Linux AG.
+ * Copyright (c) 2019-2021 Paul Wolneykien <[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 St, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Set*id helper program for PAM authentication.
+ *
+ * It is supposed to be called from mate-screensaver
+ * in order to communicate with Linux PAM as a privileged proxy.
+ * The conversation messages from the PAM stack is transmitted to
+ * mate-screensaver dialog via stdout and the received user replies
+ * read from stdin are sent back to PAM.
+ *
+ * Based on the helper written by [email protected], loosely based on
+ * unix_chkpwd by Andrew Morgan.
+ */
+
+#include <security/pam_appl.h>
+#include <security/_pam_macros.h>
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include "helper_proto.h"
+#include "gs-auth-pam.h"
+
+#define MAXLEN 1024
+
+enum {
+ UNIX_PASSED = 0,
+ UNIX_FAILED = 1
+};
+
+static char * program_name;
+
+/*
+ * Log error messages
+ */
+static void
+_log_err(int err, const char *format,...)
+{
+ va_list args;
+
+ va_start(args, format);
+ openlog(program_name, LOG_CONS | LOG_PID, LOG_AUTH);
+ vsyslog(err, format, args);
+ va_end(args);
+ closelog();
+}
+
+static void
+su_sighandler(int sig)
+{
+ if (sig > 0) {
+ _log_err(LOG_NOTICE, "caught signal %d.", sig);
+ exit(sig);
+ }
+}
+
+/*
+ * Setup signal handlers
+ */
+static void
+setup_signals(void)
+{
+ struct sigaction action;
+
+ memset((void *) &action, 0, sizeof(action));
+ action.sa_handler = su_sighandler;
+ action.sa_flags = SA_RESETHAND;
+ sigaction(SIGILL, &action, NULL);
+ sigaction(SIGTRAP, &action, NULL);
+ sigaction(SIGBUS, &action, NULL);
+ sigaction(SIGSEGV, &action, NULL);
+ action.sa_handler = SIG_IGN;
+ action.sa_flags = 0;
+ sigaction(SIGTERM, &action, NULL);
+ sigaction(SIGHUP, &action, NULL);
+ sigaction(SIGINT, &action, NULL);
+ sigaction(SIGQUIT, &action, NULL);
+ sigaction(SIGALRM, &action, NULL);
+}
+
+static int
+_converse(int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *appdata_ptr)
+{
+ struct pam_response *reply = NULL;
+ char buf[MAXLEN];
+ int num;
+ int ret = PAM_SUCCESS;
+
+ if (!(reply = malloc(sizeof(*reply) * num_msg)))
+ return PAM_CONV_ERR;
+
+ for (num = 0; num < num_msg; num++) {
+ ssize_t wt, rd;
+ size_t msg_len = strlen(msg[num]->msg);
+ wt = write_prompt (STDOUT_FILENO,
+ pam_style_to_gs_style (msg[num]->msg_style),
+ msg[num]->msg, msg_len);
+ if (wt < 0 || wt != msg_len) {
+ _log_err(LOG_ERR, "error writing promt");
+ ret = PAM_CONV_ERR;
+ break;
+ }
+
+ rd = read_msg (STDIN_FILENO, buf, sizeof (buf));
+ if (rd < 0) {
+ _log_err(LOG_ERR, "error reading reply");
+ ret = PAM_CONV_ERR;
+ break;
+ }
+
+ reply[num].resp = malloc (rd + 1);
+ if (!reply[num].resp)
+ ret = PAM_BUF_ERR;
+ else {
+ reply[num].resp_retcode = 0;
+ memcpy (reply[num].resp, buf, rd);
+ reply[num].resp[rd] = '\0';
+ }
+ }
+
+ if (ret != PAM_SUCCESS && reply != NULL) {
+ for (num = 0; num < num_msg; num++)
+ free (reply[num].resp);
+ free (reply);
+ *resp = NULL;
+ } else
+ *resp = reply;
+
+ return ret;
+}
+
+static int
+_authenticate(const char *service, const char *user)
+{
+ struct pam_conv conv = { _converse, NULL };
+ pam_handle_t *pamh;
+ int err;
+
+ err = pam_start(service, user, &conv, &pamh);
+ if (err != PAM_SUCCESS) {
+ _log_err(LOG_ERR, "pam_start(%s, %s) failed (errno %d)",
+ service, user, err);
+ return UNIX_FAILED;
+ }
+
+ err = pam_authenticate(pamh, 0);
+ if (err != PAM_SUCCESS)
+ _log_err(LOG_ERR, "pam_authenticate(%s, %s): %s",
+ service, user,
+ pam_strerror(pamh, err));
+
+ if (err == PAM_SUCCESS)
+ {
+ int err2 = pam_setcred(pamh, PAM_REFRESH_CRED);
+ if (err2 != PAM_SUCCESS)
+ _log_err(LOG_ERR, "pam_setcred(%s, %s): %s",
+ service, user,
+ pam_strerror(pamh, err2));
+ /*
+ * ignore errors on refresh credentials.
+ * If this did not work we use the old once.
+ */
+ }
+
+ pam_end(pamh, err);
+
+ if (err != PAM_SUCCESS)
+ return UNIX_FAILED;
+ return UNIX_PASSED;
+}
+
+static char *
+getuidname(uid_t uid)
+{
+ struct passwd *pw;
+ static char username[32];
+
+ pw = getpwuid(uid);
+ if (pw == NULL)
+ return NULL;
+
+ strncpy(username, pw->pw_name, sizeof(username));
+ username[sizeof(username) - 1] = '\0';
+
+ endpwent();
+ return username;
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *program_name;
+ char *service, *user;
+ int fd;
+ uid_t uid;
+
+ uid = getuid();
+
+ /*
+ * Make sure standard file descriptors are connected.
+ */
+ while ((fd = open("/dev/null", O_RDWR)) <= 2)
+ ;
+ close(fd);
+
+ /*
+ * Get the program name
+ */
+ if ((program_name = strrchr(argv[0], '/')) != NULL)
+ program_name++;
+ else
+ program_name = argv[0];
+
+ /*
+ * Catch or ignore as many signal as possible.
+ */
+ setup_signals();
+
+ /*
+ * Check argument list
+ */
+ if (argc < 2 || argc > 3) {
+ _log_err(LOG_NOTICE, "Bad number of arguments (%d)", argc);
+ return UNIX_FAILED;
+ }
+
+ /*
+ * Get the service name.
+ */
+ service = argv[1];
+
+ /*
+ * Discourage users messing around (fat chance)
+ */
+ if (isatty(STDIN_FILENO) && uid != 0) {
+ _log_err(LOG_NOTICE,
+ "Inappropriate use of Unix helper binary [UID=%d]",
+ uid);
+ fprintf(stderr,
+ "This binary is not designed for running in this way\n"
+ "-- the system administrator has been informed\n");
+ sleep(10); /* this should discourage/annoy the user */
+ return UNIX_FAILED;
+ }
+
+ /*
+ * determine the caller's user name
+ */
+ user = getuidname(uid);
+ if (argc == 3 && strcmp(user, argv[2])) {
+ user = argv[2];
+ /* Discourage use of this program as a
+ * password cracker */
+ if (uid != 0)
+ sleep(5);
+ }
+ return _authenticate(service, user);
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index f26612b..244b653 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,7 +3,7 @@ AUTOMAKE_OPTIONS = 1.7
NULL =
-saverdir = $(libexecdir)/mate-screensaver
+saverdir = $(pkglibexecdir)
themesdir = $(pkgdatadir)/themes
AM_CPPFLAGS = \
@@ -21,6 +21,7 @@ AM_CPPFLAGS = \
-DDATADIR=\""$(datadir)"\" \
-DSYSCONFDIR=\""$(sysconfdir)"\" \
-DMATELOCALEDIR=\""$(datadir)/locale"\" \
+ -DPKGLIBEXECDIR=\""$(pkglibexecdir)"\" \
-DSAVERDIR=\""$(saverdir)"\" \
-DTHEMESDIR=\""$(themesdir)"\" \
-DGTKBUILDERDIR=\"$(pkgdatadir)\" \
@@ -69,6 +70,7 @@ mate_screensaver_command_LDADD = \
AUTH_SOURCES = \
gs-auth.h \
+ gs-auth-pam.h \
gs-auth-@[email protected] \
$(NULL)
@@ -99,6 +101,11 @@ test_passwd_LDADD = \
$(AUTH_LIBS) \
$(NULL)
+if HAVE_PASSWD_HELPER
+test_passwd_LDADD += \
+ ../helper/libhelper-proto.a
+endif
+
test_watcher_SOURCES = \
test-watcher.c \
gs-watcher.h \
@@ -161,6 +168,13 @@ mate_screensaver_dialog_LDADD = \
$(LIBNOTIFY_LIBS) \
$(NULL)
+if HAVE_PASSWD_HELPER
+mate_screensaver_dialog_LDADD += \
+ ../helper/libhelper-proto.a
+../helper/libhelper-proto.a:
+ $(MAKE) -C ../helper
+endif
+
BUILT_SOURCES = \
gs-marshal.c \
gs-marshal.h \
diff --git a/src/gs-auth-helper.c b/src/gs-auth-helper.c
index acc6958..8396135 100644
--- a/src/gs-auth-helper.c
+++ b/src/gs-auth-helper.c
@@ -51,6 +51,9 @@
#include "gs-auth.h"
#include "subprocs.h"
+#include "../helper/helper_proto.h"
+#define MAXLEN 1024
+
static gboolean verbose_enabled = FALSE;
GQuark
@@ -79,85 +82,105 @@ gs_auth_get_verbose (void)
static gboolean
ext_run (const char *user,
- const char *typed_passwd,
- gboolean verbose)
+ GSAuthMessageFunc func,
+ gpointer data)
{
- int pfd[2], status;
- pid_t pid;
-
- if (pipe (pfd) < 0)
- {
- return 0;
- }
-
- if (verbose)
- {
- g_message ("ext_run (%s, %s)",
- PASSWD_HELPER_PROGRAM, user);
- }
-
- block_sigchld ();
-
- if ((pid = fork ()) < 0)
- {
- close (pfd [0]);
- close (pfd [1]);
- return FALSE;
- }
-
- 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, "mate-screensaver", user, NULL);
- if (verbose)
- {
- g_message ("%s: %s", PASSWD_HELPER_PROGRAM, g_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)
- {
- g_message ("ext_run: waitpid failed: %s\n",
- g_strerror (errno));
- }
-
- unblock_sigchld ();
- return FALSE;
- }
-
- unblock_sigchld ();
-
- if (! WIFEXITED (status) || WEXITSTATUS (status) != 0)
- {
- return FALSE;
- }
-
- return TRUE;
+ int pfd[2], r_pfd[2], status;
+ pid_t pid;
+ gboolean verbose = gs_auth_get_verbose ();
+
+ if (pipe (pfd) < 0 || pipe (r_pfd) < 0)
+ {
+ return FALSE;
+ }
+
+ if (verbose)
+ {
+ g_message ("ext_run (%s, %s)",
+ PASSWD_HELPER_PROGRAM, user);
+ }
+
+ block_sigchld ();
+
+ if ((pid = fork ()) < 0)
+ {
+ close (pfd [0]);
+ close (pfd [1]);
+ close (r_pfd [0]);
+ close (r_pfd [1]);
+ return FALSE;
+ }
+
+ if (pid == 0)
+ {
+ close (pfd [1]);
+ close (r_pfd [0]);
+ if (pfd [0] != 0)
+ {
+ dup2 (pfd [0], 0);
+ }
+ if (r_pfd [1] != 1)
+ {
+ dup2 (r_pfd [1], 1);
+ }
+
+ /* Helper is invoked as helper service-name [user] */
+ execlp (PASSWD_HELPER_PROGRAM, PASSWD_HELPER_PROGRAM, "mate-screensaver", user, NULL);
+ if (verbose)
+ {
+ g_message ("%s: %s", PASSWD_HELPER_PROGRAM, g_strerror (errno));
+ }
+
+ exit (1);
+ }
+
+ close (pfd [0]);
+ close (r_pfd [1]);
+
+ gboolean ret = FALSE;
+ while (waitpid (pid, &status, WNOHANG) == 0)
+ {
+ int msg_type;
+ char buf[MAXLEN];
+ size_t msg_len = MAXLEN;
+
+ msg_type = read_prompt (r_pfd [0], buf, &msg_len);
+ if (0 == msg_type) continue;
+ if (msg_type < 0)
+ {
+ g_message ("Error reading prompt (%d)", msg_type);
+ ret = FALSE;
+ goto exit;
+ }
+
+ char *input = NULL;
+ func (msg_type, buf, &input, data);
+
+ unsigned int input_len = input ? strlen (input) : 0;
+ ssize_t wt;
+
+ wt = write_msg (pfd [1], input, input_len);
+ if (wt < 0)
+ {
+ g_message ("Error writing prompt reply (%li)", wt);
+ ret = FALSE;
+ goto exit;
+ }
+ }
+
+ close (pfd [1]);
+ close (r_pfd [0]);
+ unblock_sigchld ();
+
+ if (! WIFEXITED (status) || WEXITSTATUS (status) != 0)
+ {
+ ret = FALSE;
+ }
+ else
+ ret = TRUE;
+
+ exit:
+ return ret;
}
gboolean
@@ -167,28 +190,7 @@ gs_auth_verify_user (const char *username,
gpointer data,
GError **error)
{
- gboolean res = FALSE;
- char *password;
-
- password = NULL;
-
- /* ask for the password for user */
- if (func != NULL)
- {
- func (GS_AUTH_MESSAGE_PROMPT_ECHO_OFF,
- "Password: ",
- &password,
- data);
- }
-
- if (password == NULL)
- {
- return FALSE;
- }
-
- res = ext_run (username, password, gs_auth_get_verbose ());
-
- return res;
+ return ext_run (username, func, data);
}
gboolean
diff --git a/src/gs-auth-pam.c b/src/gs-auth-pam.c
index bad98af..734b80c 100644
--- a/src/gs-auth-pam.c
+++ b/src/gs-auth-pam.c
@@ -46,6 +46,7 @@
#include <gtk/gtk.h>
#include "gs-auth.h"
+#include "gs-auth-pam.h"
#include "subprocs.h"
@@ -126,33 +127,6 @@ gs_auth_get_verbose (void)
return verbose_enabled;
}
-static GSAuthMessageStyle
-pam_style_to_gs_style (int pam_style)
-{
- GSAuthMessageStyle style;
-
- switch (pam_style)
- {
- case PAM_PROMPT_ECHO_ON:
- style = GS_AUTH_MESSAGE_PROMPT_ECHO_ON;
- break;
- case PAM_PROMPT_ECHO_OFF:
- style = GS_AUTH_MESSAGE_PROMPT_ECHO_OFF;
- break;
- case PAM_ERROR_MSG:
- style = GS_AUTH_MESSAGE_ERROR_MSG;
- break;
- case PAM_TEXT_INFO:
- style = GS_AUTH_MESSAGE_TEXT_INFO;
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- return style;
-}
-
static gboolean
auth_message_handler (GSAuthMessageStyle style,
const char *msg,
diff --git a/src/gs-auth-pam.h b/src/gs-auth-pam.h
new file mode 100644
index 0000000..1d8a66f
--- /dev/null
+++ b/src/gs-auth-pam.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (c) 2019 Paul Wolneykien <[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 St, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef __GS_AUTH_PAM_H
+#define __GS_AUTH_PAM_H
+
+#include "gs-auth.h"
+
+G_BEGIN_DECLS
+
+static inline GSAuthMessageStyle
+pam_style_to_gs_style (int pam_style)
+{
+ GSAuthMessageStyle style;
+
+ switch (pam_style)
+ {
+ case PAM_PROMPT_ECHO_ON:
+ style = GS_AUTH_MESSAGE_PROMPT_ECHO_ON;
+ break;
+ case PAM_PROMPT_ECHO_OFF:
+ style = GS_AUTH_MESSAGE_PROMPT_ECHO_OFF;
+ break;
+ case PAM_ERROR_MSG:
+ style = GS_AUTH_MESSAGE_ERROR_MSG;
+ break;
+ default /* PAM_TEXT_INFO */:
+ style = GS_AUTH_MESSAGE_TEXT_INFO;
+ }
+
+ return style;
+}
+
+G_END_DECLS
+
+#endif /* __GS_AUTH_PAM_H */