summaryrefslogtreecommitdiff
path: root/src/gs-auth-helper.c
diff options
context:
space:
mode:
authorPaul Wolneykien <[email protected]>2021-10-15 17:29:51 +0300
committerGitHub <[email protected]>2021-10-15 16:29:51 +0200
commited6e6065bf0e85b64317b5a34b9f7a36a0c839a6 (patch)
tree9327a81eb82146d7d43a5ec237040b12e2487de5 /src/gs-auth-helper.c
parenta2a282631d9ad88cf5e64f2379c5beb5ab3fab25 (diff)
downloadmate-screensaver-ed6e6065bf0e85b64317b5a34b9f7a36a0c839a6.tar.bz2
mate-screensaver-ed6e6065bf0e85b64317b5a34b9f7a36a0c839a6.tar.xz
Prompt-driven auth. helper
By the term "prompt-driven" I mean two-way conversation between the screensaver dialog and the PAM stack. As you probably know, PAM works by conversation with a dialog program asking the user to enter something in answer to each message it sends. In the most conventional case, the only question is "Password:" and the password is the only data the user enters. But in general, the number of questions and messages are not limited to that. The previous support of PAM helper (gs-auth-helper.c) was written and worked for the mentioned "only password" authentication scheme. For other schemes it wasn't enough. New implementation fixes that limitation. Same as the previous version of gs-auth-helper.c, the new version uses pipe interface for interprocess communication and synchronization. However, unlike the previous version, new version uses two pipes instead of a single pipe: the first one is used to transfer prompt text from PAM via the helper to the screensaver dialog, and the second one is used to transfer the user input from the dialog to helper (and then the helper replies with it back to PAM). Having that bidirectional prompt/reply channel it is possible to make as many prompt/reply passes as required by PAM. The present helper program (see the helper/ dir) is based on the helper written by [email protected], which is in turn loosely based on unix_chkpwd by Andrew Morgan. All new code is untabified under the assumption the tab width is 8. Signed-off-by: Paul Wolneykien <[email protected]>
Diffstat (limited to 'src/gs-auth-helper.c')
-rw-r--r--src/gs-auth-helper.c202
1 files changed, 102 insertions, 100 deletions
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