diff options
| -rw-r--r-- | Makefile.am | 7 | ||||
| -rw-r--r-- | configure.ac | 25 | ||||
| -rw-r--r-- | helper/Makefile.am | 27 | ||||
| -rw-r--r-- | helper/helper_proto.c | 167 | ||||
| -rw-r--r-- | helper/helper_proto.h | 53 | ||||
| -rw-r--r-- | helper/pam-helper.c | 289 | ||||
| -rw-r--r-- | src/Makefile.am | 16 | ||||
| -rw-r--r-- | src/gs-auth-helper.c | 202 | ||||
| -rw-r--r-- | src/gs-auth-pam.c | 28 | ||||
| -rw-r--r-- | src/gs-auth-pam.h | 54 | 
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 */ | 
