From 3d2d04450efb03c35c47a7c572b0b23d2bcfdf6d Mon Sep 17 00:00:00 2001 From: Antoine Jacoutot Date: Sun, 19 Jul 2015 02:19:08 +0200 Subject: [PATCH] add support for OpenBSD - OpenBSD does not use PAM nor SHADOW but bsd_auth(3) for authentication - get_kinfo_proc(): adapt FreeBSD code to OpenBSD - OpenBSD, get/setnetgrent are defined in netgroup.h and getnetgrent(3) takes a const char --- configure.ac | 21 ++- src/polkit/polkitunixprocess.c | 43 +++++- src/polkitagent/Makefile.am | 3 + src/polkitagent/polkitagenthelper-bsdauth.c | 163 +++++++++++++++++++++ .../polkitbackendinteractiveauthority.c | 8 + src/polkitbackend/polkitbackendjsauthority.c | 4 + 6 files changed, 234 insertions(+), 8 deletions(-) create mode 100644 src/polkitagent/polkitagenthelper-bsdauth.c diff --git a/configure.ac b/configure.ac index b9b64d0..85f26b9 100644 --- a/configure.ac +++ b/configure.ac @@ -167,11 +167,15 @@ fi dnl --------------------------------------------------------------------------- dnl - Check whether setnetgrent has a return value dnl --------------------------------------------------------------------------- +AC_CHECK_HEADERS([netgroup.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - #include - #include -]], [[ - int r = setnetgrent (NULL);]])], + #include + #ifdef HAVE_NETGROUP_H + #include + #else + #include + #endif +]], [[int r = setnetgrent (NULL);]])], [AC_DEFINE([HAVE_SETNETGRENT_RETURN], 1, [Define to 1 if setnetgrent has return value])]) dnl --------------------------------------------------------------------------- @@ -318,6 +322,11 @@ case $POLKIT_AUTHFW in AC_DEFINE(POLKIT_AUTHFW_SHADOW, 1, [If using the Shadow authentication framework]) ;; + bsdauth) + need_pam=no + AC_DEFINE(POLKIT_AUTHFW_BSDAUTH, 1, [If using the bsd_auth(3) authentication framework]) + ;; + *) AC_MSG_ERROR([Unknown Authentication Framework: $POLKIT_AUTHFW]) ;; @@ -326,6 +335,7 @@ esac AM_CONDITIONAL(POLKIT_AUTHFW_NONE, [test x$POLKIT_AUTHFW = xnone], [Using no authfw]) AM_CONDITIONAL(POLKIT_AUTHFW_PAM, [test x$POLKIT_AUTHFW = xpam], [Using PAM authfw]) AM_CONDITIONAL(POLKIT_AUTHFW_SHADOW, [test x$POLKIT_AUTHFW = xshadow], [Using Shadow authfw]) +AM_CONDITIONAL(POLKIT_AUTHFW_BSDAUTH, [test x$POLKIT_AUTHFW = xbsdauth], [Using bsd_auth(3) authfw]) dnl --------------------------------------------------------------------------- @@ -505,6 +515,9 @@ case "$host_os" in *freebsd*) AC_DEFINE([HAVE_FREEBSD], 1, [Is this a FreeBSD system?]) ;; + *openbsd*) + AC_DEFINE([HAVE_OPENBSD], 1, [Is this an OpenBSD system?]) + ;; esac GOBJECT_INTROSPECTION_CHECK([0.6.2]) diff --git a/src/polkit/polkitunixprocess.c b/src/polkit/polkitunixprocess.c index 9d30cd2..61790b0 100644 --- a/src/polkit/polkitunixprocess.c +++ b/src/polkit/polkitunixprocess.c @@ -29,6 +29,9 @@ #include #include #endif +#ifdef HAVE_OPENBSD +#include +#endif #include #include #include @@ -86,7 +89,7 @@ static guint64 get_start_time_for_pid (gint pid, static gint _polkit_unix_process_get_owner (PolkitUnixProcess *process, GError **error); -#ifdef HAVE_FREEBSD +#if defined(HAVE_FREEBSD) || defined(HAVE_OPENBSD) static gboolean get_kinfo_proc (gint pid, struct kinfo_proc *p); #endif @@ -554,12 +557,36 @@ get_kinfo_proc (pid_t pid, struct kinfo_proc *p) } #endif +#ifdef HAVE_OPENBSD +static gboolean +get_kinfo_proc (gint pid, struct kinfo_proc *p) +{ + int name[6]; + u_int namelen; + size_t sz; + + sz = sizeof(*p); + namelen = 0; + name[namelen++] = CTL_KERN; + name[namelen++] = KERN_PROC; + name[namelen++] = KERN_PROC_PID; + name[namelen++] = pid; + name[namelen++] = sz; + name[namelen++] = 1; + + if (sysctl (name, namelen, p, &sz, NULL, 0) == -1) + return FALSE; + + return TRUE; +} +#endif + static guint64 get_start_time_for_pid (pid_t pid, GError **error) { guint64 start_time; -#ifndef HAVE_FREEBSD +#if !defined(HAVE_FREEBSD) && !defined(HAVE_OPENBSD) gchar *filename; gchar *contents; size_t length; @@ -647,7 +674,11 @@ get_start_time_for_pid (pid_t pid, goto out; } +#ifdef HAVE_FREEBSD start_time = (guint64) p.ki_start.tv_sec; +#else + start_time = (guint64) p.p_ustart_sec; +#endif out: #endif @@ -662,7 +693,7 @@ _polkit_unix_process_get_owner (PolkitUnixProcess *process, gint result; gchar *contents; gchar **lines; -#ifdef HAVE_FREEBSD +#if defined(HAVE_FREEBSD) || defined(HAVE_OPENBSD) struct kinfo_proc p; #else gchar filename[64]; @@ -676,7 +707,7 @@ _polkit_unix_process_get_owner (PolkitUnixProcess *process, lines = NULL; contents = NULL; -#ifdef HAVE_FREEBSD +#if defined(HAVE_FREEBSD) || defined(HAVE_OPENBSD) if (get_kinfo_proc (process->pid, &p) == 0) { g_set_error (error, @@ -688,8 +719,12 @@ _polkit_unix_process_get_owner (PolkitUnixProcess *process, goto out; } +#if defined(HAVE_FREEBSD) result = p.ki_uid; #else + result = p.p_uid; +#endif +#else /* see 'man proc' for layout of the status file * diff --git a/src/polkitagent/Makefile.am b/src/polkitagent/Makefile.am index 58a55bd..4b64165 100644 --- a/src/polkitagent/Makefile.am +++ b/src/polkitagent/Makefile.am @@ -91,6 +91,9 @@ endif if POLKIT_AUTHFW_SHADOW polkit_agent_helper_1_SOURCES += polkitagenthelper-shadow.c endif +if POLKIT_AUTHFW_BSDAUTH +polkit_agent_helper_1_SOURCES += polkitagenthelper-bsdauth.c +endif polkit_agent_helper_1_CFLAGS = \ -D_POLKIT_COMPILATION \ diff --git a/src/polkitagent/polkitagenthelper-bsdauth.c b/src/polkitagent/polkitagenthelper-bsdauth.c new file mode 100644 index 0000000..b410b45 --- /dev/null +++ b/src/polkitagent/polkitagenthelper-bsdauth.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2008 Red Hat, Inc. + * Copyright (C) 2009-2010 Andrew Psaltis + * Copyright (C) 2010 Antoine Jacoutot + * + * 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 , based on + * polkitagenthelper.c which was written by + * David Zeuthen + */ + +#include "config.h" +#include "polkitagenthelperprivate.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static gboolean bsdauth_authenticate (const char *user_to_auth); + +int +main (int argc, char *argv[]) +{ + struct passwd *pw; + const char *user_to_auth; + char *cookie; + + /* 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 == 2 || 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 = read_cookie (argc, argv); + if (!cookie) + goto error; + +#ifdef PAH_DEBUG + fprintf (stderr, "polkit-agent-helper-1: user to auth is '%s'.\n", user_to_auth); +#endif /* PAH_DEBUG */ + + /* Search the password database for the user requesting authentication */ + if ((pw = getpwnam (user_to_auth)) == NULL) + { + syslog (LOG_NOTICE, "password database information request for user %s [uid=%d] failed", user_to_auth, getuid()); + fprintf(stderr, "polkit-agent-helper-1: could not get user information for '%s'", user_to_auth); + goto error; + } + + /* Check the user's identity */ + if (!bsdauth_authenticate (user_to_auth)) + { + 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; + } + +#ifdef PAH_DEBUG + fprintf (stderr, "polkit-agent-helper-1: sending D-Bus message to polkit daemon\n"); +#endif /* PAH_DEBUG */ + + /* now send a D-Bus message to the polkit 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 polkit daemon\n"); +#endif /* PAH_DEBUG */ + goto error; + } + + free (cookie); + +#ifdef PAH_DEBUG + fprintf (stderr, "polkit-agent-helper-1: successfully sent D-Bus message to polkit daemon\n"); +#endif /* PAH_DEBUG */ + + fprintf (stdout, "SUCCESS\n"); + flush_and_wait (); + return 0; + +error: + free (cookie); + fprintf (stdout, "FAILURE\n"); + flush_and_wait (); + return 1; +} + +static gboolean +bsdauth_authenticate (const char *user_to_auth) +{ + char passwd[512]; + + 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'; + + if (auth_userokay((char *)user_to_auth, NULL, "auth-polkit", passwd) == 0) + goto error; + return 1; +error: + return 0; +} diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c index 7019356..25f28a7 100644 --- a/src/polkitbackend/polkitbackendinteractiveauthority.c +++ b/src/polkitbackend/polkitbackendinteractiveauthority.c @@ -23,7 +23,11 @@ #include #include #include +#if defined HAVE_OPENBSD +#include +#else #include +#endif #include #include #include @@ -2236,7 +2240,11 @@ get_users_in_net_group (PolkitIdentity *group, for (;;) { +#if defined HAVE_OPENBSD + const char *hostname, *username, *domainname; +#else char *hostname, *username, *domainname; +#endif PolkitIdentity *user; GError *error = NULL; diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c index 097dcc5..9f9005a 100644 --- a/src/polkitbackend/polkitbackendjsauthority.c +++ b/src/polkitbackend/polkitbackendjsauthority.c @@ -24,7 +24,11 @@ #include #include #include +#if defined HAVE_OPENBSD +#include +#else #include +#endif #include #include #include -- 2.4.5