summaryrefslogtreecommitdiff
path: root/src/polkitagent
diff options
context:
space:
mode:
authorAndrew Psaltis <ampsaltis@gmail.com>2010-06-28 22:04:00 -0400
committerDavid Zeuthen <davidz@redhat.com>2010-07-02 16:31:14 -0400
commita2edcef54d2ab1a92f729e34dfa0c183b2533c61 (patch)
treeaf68d47e43be008f7f9a6d15a5d3580c8edba2cb /src/polkitagent
parent14bdfd816512a82b1ad258fa143ae5faa945df8a (diff)
downloadpolkit-a2edcef54d2ab1a92f729e34dfa0c183b2533c61.tar.gz
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: David Zeuthen <davidz@redhat.com>
Diffstat (limited to 'src/polkitagent')
-rw-r--r--src/polkitagent/Makefile.am9
-rw-r--r--src/polkitagent/polkitagenthelper-pam.c (renamed from src/polkitagent/polkitagenthelper.c)87
-rw-r--r--src/polkitagent/polkitagenthelper-shadow.c198
-rw-r--r--src/polkitagent/polkitagenthelperprivate.c106
-rw-r--r--src/polkitagent/polkitagenthelperprivate.h45
5 files changed, 363 insertions, 82 deletions
diff --git a/src/polkitagent/Makefile.am b/src/polkitagent/Makefile.am
index 3f38329..820be4d 100644
--- a/src/polkitagent/Makefile.am
+++ b/src/polkitagent/Makefile.am
@@ -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) \
diff --git a/src/polkitagent/polkitagenthelper.c b/src/polkitagent/polkitagenthelper-pam.c
index cca86db..5e8b54c 100644
--- a/src/polkitagent/polkitagenthelper.c
+++ b/src/polkitagent/polkitagenthelper-pam.c
@@ -1,5 +1,5 @@
/*
- * 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;
-}
diff --git a/src/polkitagent/polkitagenthelper-shadow.c b/src/polkitagent/polkitagenthelper-shadow.c
new file mode 100644
index 0000000..a4f73ac
--- /dev/null
+++ b/src/polkitagent/polkitagenthelper-shadow.c
@@ -0,0 +1,198 @@
+/*
+ * 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;
+}
diff --git a/src/polkitagent/polkitagenthelperprivate.c b/src/polkitagent/polkitagenthelperprivate.c
new file mode 100644
index 0000000..be495e9
--- /dev/null
+++ b/src/polkitagent/polkitagenthelperprivate.c
@@ -0,0 +1,106 @@
+/*
+ * 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 */
+}
diff --git a/src/polkitagent/polkitagenthelperprivate.h b/src/polkitagent/polkitagenthelperprivate.h
new file mode 100644
index 0000000..7294d46
--- /dev/null
+++ b/src/polkitagent/polkitagenthelperprivate.h
@@ -0,0 +1,45 @@
+/*
+ * 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 */