Skip to content

Commit

Permalink
Prompt-driven auth. helper
Browse files Browse the repository at this point in the history
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 okir@suse.de, 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 <manowar@altlinux.org>
  • Loading branch information
wolneykien committed Oct 15, 2021
1 parent a2a2826 commit ed6e606
Show file tree
Hide file tree
Showing 10 changed files with 733 additions and 135 deletions.
7 changes: 6 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
25 changes: 19 additions & 6 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1000,6 +1004,14 @@ if test "x$have_libnotify" = "xyes"; then
AC_DEFINE(WITH_LIBNOTIFY, 1, [Define for libnotify support])
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 ---------------------------------------------------------------------------
Expand Down Expand Up @@ -1117,6 +1129,7 @@ data/images/cosmos/Makefile
savers/Makefile
doc/Makefile
doc/mate-screensaver.xml
helper/Makefile
])

echo "
Expand Down
27 changes: 27 additions & 0 deletions helper/Makefile.am
Original file line number Diff line number Diff line change
@@ -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)
167 changes: 167 additions & 0 deletions helper/helper_proto.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/* Part of mate-screensaver.
*
* Copyright (c) 2019-2021 Paul Wolneykien <manowar@altlinux.org>
*
* 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;
}
53 changes: 53 additions & 0 deletions helper/helper_proto.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* Part of mate-screensaver.
*
* Copyright (c) 2019-2021 Paul Wolneykien <manowar@altlinux.org>
*
* 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 */

0 comments on commit ed6e606

Please sign in to comment.