Commit a2edcef5 authored by Andrew Psaltis's avatar Andrew Psaltis Committed by David Zeuthen

Add shadow support

Added support for the shadow authentication framework instead of PAM.
Enable it by passing --with-authfw=shadow to configure.

This is done by splitting the polkitagenthelper source into separate
parts, one that does auth with PAM, and another that does auth with
shadow, sharing functions where appropriate.

Also, all PAM-dependendent code in all other files has been #ifdef'd.
The only affected file is src/programs/pkexec.c
Signed-off-by: default avatarDavid Zeuthen <davidz@redhat.com>
parent 14bdfd81
......@@ -68,9 +68,16 @@ libpolkit_agent_1_la_LDFLAGS = -export-symbols-regex '(^polkit_.*)'
libexec_PROGRAMS = polkit-agent-helper-1
polkit_agent_helper_1_SOURCES = \
polkitagenthelper.c \
polkitagenthelperprivate.c polkitagenthelperprivate.h \
$(NULL)
if POLKIT_AUTHFW_PAM
polkit_agent_helper_1_SOURCES += polkitagenthelper-pam.c
endif
if POLKIT_AUTHFW_SHADOW
polkit_agent_helper_1_SOURCES += polkitagenthelper-shadow.c
endif
polkit_agent_helper_1_CFLAGS = \
-D_POLKIT_COMPILATION \
$(GLIB_CFLAGS) \
......
/*
* Copyright (C) 2008 Red Hat, Inc.
* Copyright (C) 2008, 2010 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -20,6 +20,8 @@
*/
#include "config.h"
#include "polkitagenthelperprivate.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -31,31 +33,6 @@
#include <polkit/polkit.h>
#ifdef HAVE_SOLARIS
# define LOG_AUTHPRIV (10<<3)
#endif
#ifndef HAVE_CLEARENV
extern char **environ;
static int
clearenv (void)
{
if (environ != NULL)
environ[0] = NULL;
return 0;
}
#endif
/* Development aid: define PAH_DEBUG to get debugging output. Do _NOT_
* enable this in production builds; it may leak passwords and other
* sensitive information.
*/
#undef PAH_DEBUG
// #define PAH_DEBUG
static gboolean send_dbus_message (const char *cookie, const char *user);
static int conversation_function (int n, const struct pam_message **msg, struct pam_response **resp, void *data);
int
......@@ -72,7 +49,7 @@ main (int argc, char *argv[])
pam_h = NULL;
/* clear the entire environment to avoid attacks using with libraries honoring environment variables */
if (clearenv () != 0)
if (_polkit_clearenv () != 0)
goto error;
/* set a minimal environment */
......@@ -193,9 +170,7 @@ main (int argc, char *argv[])
#endif /* PAH_DEBUG */
fprintf (stdout, "SUCCESS\n");
fflush (stdout);
fflush (stderr);
usleep (10 * 1000); /* since fflush(3) seems buggy */
flush_and_wait();
return 0;
error:
......@@ -203,9 +178,7 @@ error:
pam_end (pam_h, rc);
fprintf (stdout, "FAILURE\n");
fflush (stdout);
fflush (stderr);
usleep (10 * 1000); /* since fflush(3) seems buggy */
flush_and_wait();
return 1;
}
......@@ -289,51 +262,3 @@ error:
*resp = NULL;
return PAM_CONV_ERR;
}
static gboolean
send_dbus_message (const char *cookie, const char *user)
{
PolkitAuthority *authority;
PolkitIdentity *identity;
GError *error;
gboolean ret;
ret = FALSE;
error = NULL;
g_type_init ();
authority = polkit_authority_get ();
identity = polkit_unix_user_new_for_name (user, &error);
if (identity == NULL)
{
g_printerr ("Error constructing identity: %s\n", error->message);
g_error_free (error);
goto out;
}
if (!polkit_authority_authentication_agent_response_sync (authority,
cookie,
identity,
NULL,
&error))
{
g_printerr ("polkit-agent-helper-1: error response to PolicyKit daemon: %s\n", error->message);
g_error_free (error);
goto out;
}
ret = TRUE;
out:
if (identity != NULL)
g_object_unref (identity);
if (authority != NULL)
g_object_unref (authority);
return ret;
}
/*
* Copyright (C) 2008 Red Hat, Inc.
* Copyright (C) 2009-2010 Andrew Psaltis <ampsaltis@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Andrew Psaltis <ampsaltis@gmail.com>, based on
* polkitagenthelper.c which was written by
* David Zeuthen <davidz@redhat.com>
*/
#include "config.h"
#include "polkitagenthelperprivate.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
#include <shadow.h>
#include <grp.h>
#include <pwd.h>
#include <time.h>
#include <polkit/polkit.h>
static gboolean shadow_authenticate (struct spwd *shadow);
int
main (int argc, char *argv[])
{
struct spwd *shadow;
const char *user_to_auth;
const char *cookie;
time_t now;
/* clear the entire environment to avoid attacks with
libraries honoring environment variables */
if (_polkit_clearenv () != 0)
goto error;
/* set a minimal environment */
setenv ("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1);
/* check that we are setuid root */
if (geteuid () != 0)
{
fprintf (stderr, "polkit-agent-helper-1: needs to be setuid root\n");
goto error;
}
openlog ("polkit-agent-helper-1", LOG_CONS | LOG_PID, LOG_AUTHPRIV);
/* check for correct invocation */
if (argc != 3)
{
syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ());
fprintf (stderr, "polkit-agent-helper-1: wrong number of arguments. This incident has been logged.\n");
goto error;
}
if (getuid () != 0)
{
/* check we're running with a non-tty stdin */
if (isatty (STDIN_FILENO) != 0)
{
syslog (LOG_NOTICE, "inappropriate use of helper, stdin is a tty [uid=%d]", getuid ());
fprintf (stderr, "polkit-agent-helper-1: inappropriate use of helper, stdin is a tty. This incident has been logged.\n");
goto error;
}
}
user_to_auth = argv[1];
cookie = argv[2];
#ifdef PAH_DEBUG
fprintf (stderr, "polkit-agent-helper-1: user to auth is '%s'.\n", user_to_auth);
#endif /* PAH_DEBUG */
/* Ask shadow about the user requesting authentication */
shadow = getspnam (user_to_auth);
if (shadow == NULL)
{
syslog (LOG_NOTICE, "shadow file data information request for user '%s' [uid=%d] failed", user_to_auth, getuid ());
fprintf(stderr, "polkit-agent-helper-1: could not get shadow information for '%s'", user_to_auth);
goto error;
}
/* Check the user's identity */
if (shadow_authenticate (shadow) == FALSE)
{
syslog (LOG_NOTICE, "authentication failure [uid=%d] trying to authenticate '%s'", getuid (), user_to_auth);
fprintf (stderr, "polkit-agent-helper-1: authentication failure. This incident has been logged.\n");
goto error;
}
/* Check whether the user's password has expired */
now = time (NULL);
if (shadow->sp_max >= 0 && (shadow->sp_lstchg + shadow->sp_max) * 60 * 60 * 24 <= now)
{
syslog (LOG_NOTICE, "password expired for user '%s' [uid=%d] trying to authenticate", user_to_auth, getuid ());
fprintf (stderr, "polkit-agent-helper-1: authorization failure. This incident has been logged.\n");
goto error;
}
/* Check whether the user's password has aged (and account expired along
* with it)
*/
if (shadow->sp_inact >= 0 && (shadow->sp_lstchg + shadow->sp_max + shadow->sp_inact) * 60 * 60 * 24 <= now)
{
syslog (LOG_NOTICE, "password aged for user '%s' [uid=%d] trying to authenticate", user_to_auth, getuid ());
fprintf (stderr, "polkit-agent-helper-1: authorization failure. This incident has been logged.\n");
goto error;
}
/* Check whether the user's account has expired */
if (shadow->sp_expire >= 0 && shadow->sp_expire * 60 * 60 * 24 <= now)
{
syslog (LOG_NOTICE, "account expired for user '%s' [uid=%d] trying to authenticate", user_to_auth, getuid ());
fprintf (stderr, "polkit-agent-helper-1: authorization failure. This incident has been logged.\n");
goto error;
}
#ifdef PAH_DEBUG
fprintf (stderr, "polkit-agent-helper-1: sending D-Bus message to PolicyKit daemon\n");
#endif /* PAH_DEBUG */
/* now send a D-Bus message to the PolicyKit daemon that
* includes a) the cookie; and b) the user we authenticated
*/
if (!send_dbus_message (cookie, user_to_auth))
{
#ifdef PAH_DEBUG
fprintf (stderr, "polkit-agent-helper-1: error sending D-Bus message to PolicyKit daemon\n");
#endif /* PAH_DEBUG */
goto error;
}
#ifdef PAH_DEBUG
fprintf (stderr, "polkit-agent-helper-1: successfully sent D-Bus message to PolicyKit daemon\n");
#endif /* PAH_DEBUG */
fprintf (stdout, "SUCCESS\n");
flush_and_wait ();
return 0;
error:
fprintf (stdout, "FAILURE\n");
flush_and_wait ();
return 1;
}
static gboolean
shadow_authenticate (struct spwd *shadow)
{
char passwd[512], *crypt_pass;
fprintf (stdout, "PAM_PROMPT_ECHO_OFF password:\n");
fflush (stdout);
usleep (10 * 1000); /* since fflush(3) seems buggy */
if (fgets (passwd, sizeof (passwd), stdin) == NULL)
goto error;
if (strlen (passwd) > 0 && passwd[strlen (passwd) - 1] == '\n')
passwd[strlen (passwd) - 1] = '\0';
/* Use the encrypted password as the salt, according to the crypt(3) man page,
* it will perform whatever encryption method is specified in /etc/shadow
*/
crypt_pass = crypt (passwd, shadow->sp_pwdp);
if (crypt_pass == NULL)
goto error;
if (strcmp (shadow->sp_pwdp, crypt (passwd, shadow->sp_pwdp)) != 0)
goto error;
return 1;
error:
return 0;
}
/*
* Copyright (C) 2009-2010 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* Authors: David Zeuthen <davidz@redhat.com>,
* Andrew Psaltis <ampsaltis@gmail.com>
*/
#include "config.h"
#include "polkitagenthelperprivate.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef HAVE_CLEARENV
extern char **environ;
int
_polkit_clearenv (void)
{
if (environ != NULL)
environ[0] = NULL;
return 0;
}
#else
int
_polkit_clearenv (void)
{
return clearenv ();
}
#endif
gboolean
send_dbus_message (const char *cookie, const char *user)
{
PolkitAuthority *authority;
PolkitIdentity *identity;
GError *error;
gboolean ret;
ret = FALSE;
error = NULL;
g_type_init ();
authority = polkit_authority_get ();
identity = polkit_unix_user_new_for_name (user, &error);
if (identity == NULL)
{
g_printerr ("Error constructing identity: %s\n", error->message);
g_error_free (error);
goto out;
}
if (!polkit_authority_authentication_agent_response_sync (authority,
cookie,
identity,
NULL,
&error))
{
g_printerr ("polkit-agent-helper-1: error response to PolicyKit daemon: %s\n", error->message);
g_error_free (error);
goto out;
}
ret = TRUE;
out:
if (identity != NULL)
g_object_unref (identity);
if (authority != NULL)
g_object_unref (authority);
return ret;
}
/* fflush(3) stdin and stdout and wait a little bit.
* This replaces the three-line commands at the bottom of
* polkit-agent-helper-1's main() function.
*/
void
flush_and_wait ()
{
fflush (stdout);
fflush (stderr);
usleep (10 * 1000); /* since fflush(3) seems buggy */
}
/*
* Copyright (C) 2009-2010 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* Authors: David Zeuthen <davidz@redhat.com>,
* Andrew Psaltis <ampsalits@gmail.com>
*/
#ifndef __POLKIT_AGENT_HELPER_PRIVATE_H
#define __POLKIT_AGENT_HELPER_PRIVATE_H
#define _GNU_SOURCE
#include <polkit/polkit.h>
/* Development aid: define PAH_DEBUG to get debugging output. Do _NOT_
* enable this in production builds; it may leak passwords and other
* sensitive information.
*/
#undef PAH_DEBUG
// #define PAH_DEBUG
#ifdef HAVE_SOLARIS
# define LOG_AUTHPRIV (10<<3)
#endif
int _polkit_clearenv (void);
gboolean send_dbus_message (const char *cookie, const char *user);
void flush_and_wait ();
#endif /* __POLKIT_AGENT_HELPER_PRIVATE_H */
......@@ -34,7 +34,11 @@
#include <grp.h>
#include <pwd.h>
#include <errno.h>
#ifdef POLKIT_AUTHFW_PAM
#include <security/pam_appl.h>
#endif /* POLKIT_AUTHFW_PAM */
#include <syslog.h>
#include <stdarg.h>
......@@ -115,6 +119,7 @@ log_message (gint level,
/* ---------------------------------------------------------------------------------------------------- */
#ifdef POLKIT_AUTHFW_PAM
static int
pam_conversation_function (int n,
const struct pam_message **msg,
......@@ -167,6 +172,7 @@ out:
pam_end (pam_h, rc);
return ret;
}
#endif /* POLKIT_AUTHFW_PAM */
/* ---------------------------------------------------------------------------------------------------- */
......@@ -741,10 +747,12 @@ main (int argc, char *argv[])
* TODO: The question here is whether we should clear the limits before applying them?
* As evident above, neither su(1) (and, for that matter, nor sudo(8)) does this.
*/
#ifdef POLKIT_AUTHFW_PAM
if (!open_session (pw->pw_name))
{
goto out;
}
#endif /* POLKIT_AUTHFW_PAM */
/* become the user */
if (setgroups (0, NULL) != 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment