From 24b3cc219227a123f089b5acadd61745ca613408 Mon Sep 17 00:00:00 2001 From: Christian Kellner Date: Wed, 1 Feb 2017 15:04:45 +0100 Subject: [PATCH] device: extract polkit related functions to auth.c The functsion related to authorization are actually not tied to a specific device (they only access the PolkitAuthority member of device). Therefore this function were made device-independent and moved to auth.c so they can be re-used from, e.g. manager.c. https://bugs.freedesktop.org/show_bug.cgi?id=99811 --- src/Makefile.am | 2 +- src/auth.c | 129 ++++++++++++++++++++++++++++++++++++++++++ src/auth.h | 46 +++++++++++++++ src/device.c | 173 +++++++++----------------------------------------------- 4 files changed, 203 insertions(+), 147 deletions(-) create mode 100644 src/auth.c create mode 100644 src/auth.h diff --git a/src/Makefile.am b/src/Makefile.am index f74e424..5ff8417 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,7 +10,7 @@ noinst_LTLIBRARIES = libfprintd.la AM_CFLAGS = $(WARN_CFLAGS) $(FPRINT_CFLAGS) $(DAEMON_CFLAGS) -DLOCALEDIR=\""$(datadir)/locale"\" -DPLUGINDIR=\""$(libdir)/fprintd/modules"\" libfprintd_la_SOURCES = \ - manager.c device.c \ + auth.c manager.c device.c \ $(MARSHALFILES) \ fprintd.h libfprintd_la_LIBADD = $(FPRINT_LIBS) $(DAEMON_LIBS) diff --git a/src/auth.c b/src/auth.c new file mode 100644 index 0000000..239c54f --- /dev/null +++ b/src/auth.c @@ -0,0 +1,129 @@ + +#include "auth.h" +#include "fprintd.h" + +#include + +extern DBusGConnection *fprintd_dbus_conn; + +gboolean +fprint_check_polkit_for_action (PolkitAuthority *authority, + DBusGMethodInvocation *context, + const char *action, + GError **error) +{ + const char *sender; + PolkitSubject *subject; + PolkitAuthorizationResult *result; + GError *_error = NULL; + + /* Check that caller is privileged */ + sender = dbus_g_method_get_sender (context); + subject = polkit_system_bus_name_new (sender); + + result = polkit_authority_check_authorization_sync (authority, + subject, + action, + NULL, + POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, + NULL, &_error); + g_object_unref (subject); + + if (result == NULL) { + g_set_error (error, FPRINT_ERROR, + FPRINT_ERROR_PERMISSION_DENIED, + "Not Authorized: %s", _error->message); + g_error_free (_error); + return FALSE; + } + + if (!polkit_authorization_result_get_is_authorized (result)) { + g_set_error (error, FPRINT_ERROR, + FPRINT_ERROR_PERMISSION_DENIED, + "Not Authorized: %s", action); + g_object_unref (result); + return FALSE; + } + + g_object_unref (result); + + return TRUE; +} + + +gboolean +fprint_check_polkit_for_actions (PolkitAuthority *authority, + DBusGMethodInvocation *context, + const char *action1, + const char *action2, + GError **error) +{ + if (fprint_check_polkit_for_action (authority, context, action1, error) != FALSE) + return TRUE; + + g_error_free (*error); + *error = NULL; + + return fprint_check_polkit_for_action (authority, context, action2, error); +} + +char * +fprint_check_for_username (PolkitAuthority *authority, + DBusGMethodInvocation *context, + const char *username, + char **ret_sender, + GError **error) +{ + DBusConnection *conn; + DBusError dbus_error; + char *sender; + unsigned long uid; + struct passwd *user; + char *client_username; + + /* Get details about the current sender, and username/uid */ + conn = dbus_g_connection_get_connection (fprintd_dbus_conn); + sender = dbus_g_method_get_sender (context); + dbus_error_init (&dbus_error); + uid = dbus_bus_get_unix_user (conn, sender, &dbus_error); + + if (dbus_error_is_set(&dbus_error)) { + g_free (sender); + dbus_set_g_error (error, &dbus_error); + return NULL; + } + + user = getpwuid (uid); + if (user == NULL) { + g_free (sender); + g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_INTERNAL, + "Failed to get information about user UID %lu", uid); + return NULL; + } + client_username = g_strdup (user->pw_name); + + /* The current user is usually allowed to access their + * own data, this should be followed by PolicyKit checks + * anyway */ + if (username == NULL || *username == '\0' || g_str_equal (username, client_username)) { + if (ret_sender != NULL) + *ret_sender = sender; + else + g_free (sender); + return client_username; + } + + /* If we're not allowed to set a different username, + * then fail */ + if (fprint_check_polkit_for_action (authority, context, "net.reactivated.fprint.device.setusername", error) == FALSE) { + g_free (sender); + return NULL; + } + + if (ret_sender != NULL) + *ret_sender = sender; + else + g_free (sender); + + return g_strdup (username); +} diff --git a/src/auth.h b/src/auth.h new file mode 100644 index 0000000..71480f9 --- /dev/null +++ b/src/auth.h @@ -0,0 +1,46 @@ +/* + * + * Copyright (C) 2008 Daniel Drake + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __FPRINTD_AUTH_H__ +#define __FPRINTD_AUTH_H__ + +#include +#include +#include +#include + + +gboolean fprint_check_polkit_for_action (PolkitAuthority *authority, + DBusGMethodInvocation *context, + const char *action, + GError **error); + +gboolean fprint_check_polkit_for_actions (PolkitAuthority *authority, + DBusGMethodInvocation *context, + const char *action1, + const char *action2, + GError **error); + +char * fprint_check_for_username (PolkitAuthority *authority, + DBusGMethodInvocation *context, + const char *username, + char **ret_sender, + GError **error); + +#endif diff --git a/src/device.c b/src/device.c index df26f3a..bcd6814 100644 --- a/src/device.c +++ b/src/device.c @@ -27,12 +27,12 @@ #include #include -#include #include #include "fprintd-marshal.h" #include "fprintd.h" #include "storage.h" +#include "auth.h" static char *fingers[] = { "left-thumb", @@ -398,125 +398,6 @@ _fprint_device_check_claimed (FprintDevice *rdev, return retval; } -static gboolean -_fprint_device_check_polkit_for_action (FprintDevice *rdev, DBusGMethodInvocation *context, const char *action, GError **error) -{ - FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev); - const char *sender; - PolkitSubject *subject; - PolkitAuthorizationResult *result; - GError *_error = NULL; - - /* Check that caller is privileged */ - sender = dbus_g_method_get_sender (context); - subject = polkit_system_bus_name_new (sender); - - result = polkit_authority_check_authorization_sync (priv->auth, - subject, - action, - NULL, - POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, - NULL, &_error); - g_object_unref (subject); - - if (result == NULL) { - g_set_error (error, FPRINT_ERROR, - FPRINT_ERROR_PERMISSION_DENIED, - "Not Authorized: %s", _error->message); - g_error_free (_error); - return FALSE; - } - - if (!polkit_authorization_result_get_is_authorized (result)) { - g_set_error (error, FPRINT_ERROR, - FPRINT_ERROR_PERMISSION_DENIED, - "Not Authorized: %s", action); - g_object_unref (result); - return FALSE; - } - - g_object_unref (result); - - return TRUE; -} - -static gboolean -_fprint_device_check_polkit_for_actions (FprintDevice *rdev, - DBusGMethodInvocation *context, - const char *action1, - const char *action2, - GError **error) -{ - if (_fprint_device_check_polkit_for_action (rdev, context, action1, error) != FALSE) - return TRUE; - - g_error_free (*error); - *error = NULL; - - return _fprint_device_check_polkit_for_action (rdev, context, action2, error); -} - -static char * -_fprint_device_check_for_username (FprintDevice *rdev, - DBusGMethodInvocation *context, - const char *username, - char **ret_sender, - GError **error) -{ - DBusConnection *conn; - DBusError dbus_error; - char *sender; - unsigned long uid; - struct passwd *user; - char *client_username; - - /* Get details about the current sender, and username/uid */ - conn = dbus_g_connection_get_connection (fprintd_dbus_conn); - sender = dbus_g_method_get_sender (context); - dbus_error_init (&dbus_error); - uid = dbus_bus_get_unix_user (conn, sender, &dbus_error); - - if (dbus_error_is_set(&dbus_error)) { - g_free (sender); - dbus_set_g_error (error, &dbus_error); - return NULL; - } - - user = getpwuid (uid); - if (user == NULL) { - g_free (sender); - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_INTERNAL, - "Failed to get information about user UID %lu", uid); - return NULL; - } - client_username = g_strdup (user->pw_name); - - /* The current user is usually allowed to access their - * own data, this should be followed by PolicyKit checks - * anyway */ - if (username == NULL || *username == '\0' || g_str_equal (username, client_username)) { - if (ret_sender != NULL) - *ret_sender = sender; - else - g_free (sender); - return client_username; - } - - /* If we're not allowed to set a different username, - * then fail */ - if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.setusername", error) == FALSE) { - g_free (sender); - return NULL; - } - - if (ret_sender != NULL) - *ret_sender = sender; - else - g_free (sender); - - return g_strdup (username); -} - static void action_stop_cb(struct fp_dev *dev, void *user_data) { gboolean *done = (gboolean *) user_data; @@ -639,11 +520,11 @@ static void fprint_device_claim(FprintDevice *rdev, g_assert (priv->sender == NULL); sender = NULL; - user = _fprint_device_check_for_username (rdev, - context, - username, - &sender, - &error); + user = fprint_check_for_username (priv->auth, + context, + username, + &sender, + &error); if (user == NULL) { g_free (sender); dbus_g_method_return_error (context, error); @@ -651,10 +532,10 @@ static void fprint_device_claim(FprintDevice *rdev, return; } - if (_fprint_device_check_polkit_for_actions (rdev, context, - "net.reactivated.fprint.device.verify", - "net.reactivated.fprint.device.enroll", - &error) == FALSE) { + if (fprint_check_polkit_for_actions (priv->auth, context, + "net.reactivated.fprint.device.verify", + "net.reactivated.fprint.device.enroll", + &error) == FALSE) { g_free (sender); g_free (user); dbus_g_method_return_error (context, error); @@ -721,7 +602,7 @@ static void fprint_device_release(FprintDevice *rdev, } /* People that can claim can also release */ - if (_fprint_device_check_polkit_for_actions (rdev, context, + if (fprint_check_polkit_for_actions (priv->auth, context, "net.reactivated.fprint.device.verify", "net.reactivated.fprint.device.enroll", &error) == FALSE) { @@ -801,7 +682,7 @@ static void fprint_device_verify_start(FprintDevice *rdev, return; } - if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.verify", &error) == FALSE) { + if (fprint_check_polkit_for_action (priv->auth, context, "net.reactivated.fprint.device.verify", &error) == FALSE) { dbus_g_method_return_error (context, error); g_error_free (error); return; @@ -936,7 +817,7 @@ static void fprint_device_verify_stop(FprintDevice *rdev, return; } - if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.verify", &error) == FALSE) { + if (fprint_check_polkit_for_action (priv->auth, context, "net.reactivated.fprint.device.verify", &error) == FALSE) { dbus_g_method_return_error (context, error); return; } @@ -1034,7 +915,7 @@ static void fprint_device_enroll_start(FprintDevice *rdev, return; } - if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.enroll", &error) == FALSE) { + if (fprint_check_polkit_for_action (priv->auth, context, "net.reactivated.fprint.device.enroll", &error) == FALSE) { dbus_g_method_return_error (context, error); return; } @@ -1086,7 +967,7 @@ static void fprint_device_enroll_stop(FprintDevice *rdev, return; } - if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.enroll", &error) == FALSE) { + if (fprint_check_polkit_for_action (priv->auth, context, "net.reactivated.fprint.device.enroll", &error) == FALSE) { dbus_g_method_return_error (context, error); return; } @@ -1126,18 +1007,18 @@ static void fprint_device_list_enrolled_fingers(FprintDevice *rdev, GPtrArray *ret; char *user, *sender; - user = _fprint_device_check_for_username (rdev, - context, - username, - NULL, - &error); + user = fprint_check_for_username (priv->auth, + context, + username, + NULL, + &error); if (user == NULL) { dbus_g_method_return_error (context, error); g_error_free (error); return; } - if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.verify", &error) == FALSE) { + if (fprint_check_polkit_for_action (priv->auth, context, "net.reactivated.fprint.device.verify", &error) == FALSE) { g_free (user); dbus_g_method_return_error (context, error); return; @@ -1177,18 +1058,18 @@ static void fprint_device_delete_enrolled_fingers(FprintDevice *rdev, guint i; char *user, *sender; - user = _fprint_device_check_for_username (rdev, - context, - username, - NULL, - &error); + user = fprint_check_for_username (priv->auth, + context, + username, + NULL, + &error); if (user == NULL) { dbus_g_method_return_error (context, error); g_error_free (error); return; } - if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.enroll", &error) == FALSE) { + if (fprint_check_polkit_for_action (priv->auth, context, "net.reactivated.fprint.device.enroll", &error) == FALSE) { g_free (user); dbus_g_method_return_error (context, error); return; -- 2.9.3