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 */ |