summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/daemon.c33
-rw-r--r--src/user.c156
-rw-r--r--src/util.c72
-rw-r--r--src/util.h4
4 files changed, 87 insertions, 178 deletions
diff --git a/src/daemon.c b/src/daemon.c
index 50ae3b9..7f6a088 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -1022,8 +1022,6 @@ daemon_create_user_authorized_cb (Daemon *daemon,
CreateUserData *cd = data;
User *user;
GError *error;
- gchar *std_err, *std_out;
- gint status;
gchar *argv[8];
if (getpwnam (cd->user_name) != NULL) {
@@ -1055,27 +1053,13 @@ daemon_create_user_authorized_cb (Daemon *daemon,
argv[5] = NULL;
}
- std_out = NULL;
- std_err = NULL;
error = NULL;
- if (!g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, &std_out, &std_err, &status, &error)) {
+ if (!spawn_with_login_uid (context, argv, &error)) {
throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
g_error_free (error);
- g_free (std_out);
- g_free (std_err);
return;
}
- if (WEXITSTATUS (status) != 0) {
- throw_error (context, ERROR_FAILED, "useradd returned an error: %s", std_err);
- g_free (std_out);
- g_free (std_err);
- return;
- }
-
- g_free (std_out);
- g_free (std_err);
-
user = daemon_local_find_user_by_name (daemon, cd->user_name);
dbus_g_method_return (context, user_local_get_object_path (user));
@@ -1121,8 +1105,6 @@ daemon_delete_user_authorized_cb (Daemon *daemon,
{
DeleteUserData *ud = data;
GError *error;
- gchar *std_err, *std_out;
- gint status;
gchar *filename;
struct passwd *pwent;
gchar *argv[4];
@@ -1148,21 +1130,10 @@ daemon_delete_user_authorized_cb (Daemon *daemon,
argv[2] = NULL;
}
- std_out = NULL;
- std_err = NULL;
error = NULL;
- if (!g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, &std_out, &std_err, &status, &error)) {
+ if (!spawn_with_login_uid (context, argv, &error)) {
throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
g_error_free (error);
- g_free (std_out);
- g_free (std_err);
- return;
- }
-
- if (WEXITSTATUS (status) != 0) {
- throw_error (context, ERROR_FAILED, "userdel returned an error: %s", std_err);
- g_free (std_out);
- g_free (std_err);
return;
}
diff --git a/src/user.c b/src/user.c
index 6501922..a1dff91 100644
--- a/src/user.c
+++ b/src/user.c
@@ -769,8 +769,6 @@ user_change_real_name_authorized_cb (Daemon *daemon,
{
gchar *name = data;
GError *error;
- gint status;
- gchar *std_out, *std_err;
gchar *argv[5];
if (g_strcmp0 (user->real_name, name) != 0) {
@@ -784,27 +782,13 @@ user_change_real_name_authorized_cb (Daemon *daemon,
argv[3] = user->user_name;
argv[4] = NULL;
- std_out = NULL;
- std_err = NULL;
error = NULL;
- if (!g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, &std_out, &std_err, &status, &error)) {
+ if (!spawn_with_login_uid (context, argv, &error)) {
throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
g_error_free (error);
- g_free (std_out);
- g_free (std_err);
return;
}
- if (WEXITSTATUS (status) != 0) {
- throw_error (context, ERROR_FAILED, "usermod returned an error: %s", std_err);
- g_free (std_out);
- g_free (std_err);
- return;
- }
-
- g_free (std_out);
- g_free (std_err);
-
g_free (user->real_name);
user->real_name = g_strdup (name);
@@ -865,8 +849,6 @@ user_change_user_name_authorized_cb (Daemon *daemon,
gchar *name = data;
gchar *old_name;
GError *error;
- gint status;
- gchar *std_out, *std_err;
gchar *argv[5];
if (g_strcmp0 (user->user_name, name) != 0) {
@@ -881,27 +863,13 @@ user_change_user_name_authorized_cb (Daemon *daemon,
argv[3] = user->user_name;
argv[4] = NULL;
- std_out = NULL;
- std_err = NULL;
error = NULL;
- if (!g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, &std_out, &std_err, &status, &error)) {
+ if (!spawn_with_login_uid (context, argv, &error)) {
throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
g_error_free (error);
- g_free (std_out);
- g_free (std_err);
return;
}
- if (WEXITSTATUS (status) != 0) {
- throw_error (context, ERROR_FAILED, "usermod returned an error: %s", std_err);
- g_free (std_out);
- g_free (std_err);
- return;
- }
-
- g_free (std_out);
- g_free (std_err);
-
g_free (user->user_name);
user->user_name = g_strdup (name);
@@ -1154,8 +1122,6 @@ user_change_home_dir_authorized_cb (Daemon *daemon,
{
gchar *home_dir = data;
GError *error;
- gint status;
- gchar *std_out, *std_err;
gchar *argv[6];
if (g_strcmp0 (user->home_dir, home_dir) != 0) {
@@ -1170,27 +1136,13 @@ user_change_home_dir_authorized_cb (Daemon *daemon,
argv[4] = user->user_name;
argv[5] = NULL;
- std_out = NULL;
- std_err = NULL;
error = NULL;
- if (!g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, &std_out, &std_err, &status, &error)) {
+ if (!spawn_with_login_uid (context, argv, &error)) {
throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
g_error_free (error);
- g_free (std_out);
- g_free (std_err);
return;
}
- if (WEXITSTATUS (status) != 0) {
- throw_error (context, ERROR_FAILED, "usermod returned an error: %s", std_err);
- g_free (std_out);
- g_free (std_err);
- return;
- }
-
- g_free (std_out);
- g_free (std_err);
-
g_free (user->home_dir);
user->home_dir = g_strdup (home_dir);
@@ -1247,8 +1199,6 @@ user_change_shell_authorized_cb (Daemon *daemon,
{
gchar *shell = data;
GError *error;
- gint status;
- gchar *std_out, *std_err;
gchar *argv[5];
if (g_strcmp0 (user->shell, shell) != 0) {
@@ -1262,27 +1212,13 @@ user_change_shell_authorized_cb (Daemon *daemon,
argv[3] = user->user_name;
argv[4] = NULL;
- std_out = NULL;
- std_err = NULL;
error = NULL;
- if (!g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, &std_out, &std_err, &status, &error)) {
+ if (!spawn_with_login_uid (context, argv, &error)) {
throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
g_error_free (error);
- g_free (std_out);
- g_free (std_err);
- return;
- }
-
- if (WEXITSTATUS (status) != 0) {
- throw_error (context, ERROR_FAILED, "usermod returned an error: %s", std_err);
- g_free (std_out);
- g_free (std_err);
return;
}
- g_free (std_out);
- g_free (std_err);
-
g_free (user->shell);
user->shell = g_strdup (shell);
@@ -1532,8 +1468,6 @@ user_change_locked_authorized_cb (Daemon *daemon,
{
gboolean locked = GPOINTER_TO_INT (data);
GError *error;
- gint status;
- gchar *std_out, *std_err;
gchar *argv[4];
if (user->locked != locked) {
@@ -1545,27 +1479,13 @@ user_change_locked_authorized_cb (Daemon *daemon,
argv[2] = user->user_name;
argv[3] = NULL;
- std_out = NULL;
- std_err = NULL;
error = NULL;
- if (!g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, &std_out, &std_err, &status, &error)) {
+ if (!spawn_with_login_uid (context, argv, &error)) {
throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
g_error_free (error);
- g_free (std_out);
- g_free (std_err);
- return;
- }
-
- if (WEXITSTATUS (status) != 0) {
- throw_error (context, ERROR_FAILED, "usermod returned an error: %s", std_err);
- g_free (std_out);
- g_free (std_err);
return;
}
- g_free (std_out);
- g_free (std_err);
-
user->locked = locked;
g_signal_emit (user, signals[CHANGED], 0);
@@ -1602,8 +1522,6 @@ user_change_account_type_authorized_cb (Daemon *daemon,
{
gint account_type = GPOINTER_TO_INT (data);
GError *error;
- gint status;
- gchar *std_out, *std_err;
gid_t groups[20];
gint n_groups;
GString *str;
@@ -1664,27 +1582,13 @@ user_change_account_type_authorized_cb (Daemon *daemon,
g_string_free (str, FALSE);
- std_out = NULL;
- std_err = NULL;
error = NULL;
- if (!g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, &std_out, &std_err, &status, &error)) {
+ if (!spawn_with_login_uid (context, argv, &error)) {
throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
g_error_free (error);
- g_free (std_out);
- g_free (std_err);
return;
}
- if (WEXITSTATUS (status) != 0) {
- throw_error (context, ERROR_FAILED, "usermod returned an error: %s", std_err);
- g_free (std_out);
- g_free (std_err);
- return;
- }
-
- g_free (std_out);
- g_free (std_err);
-
user->account_type = account_type;
g_signal_emit (user, signals[CHANGED], 0);
@@ -1726,8 +1630,6 @@ user_change_password_mode_authorized_cb (Daemon *daemon,
{
gint mode = GPOINTER_TO_INT (data);
GError *error;
- gint status;
- gchar *std_out, *std_err;
gchar *argv[4];
if (user->password_mode != mode) {
@@ -1745,27 +1647,13 @@ user_change_password_mode_authorized_cb (Daemon *daemon,
argv[2] = user->user_name;
argv[3] = NULL;
- std_out = NULL;
- std_err = NULL;
error = NULL;
- if (!g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, &std_out, &std_err, &status, &error)) {
+ if (!spawn_with_login_uid (context, argv, &error)) {
throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
g_error_free (error);
- g_free (std_out);
- g_free (std_err);
return;
}
- if (WEXITSTATUS (status) != 0) {
- throw_error (context, ERROR_FAILED, "passwd returned an error: %s", std_err);
- g_free (std_out);
- g_free (std_err);
- return;
- }
-
- g_free (std_out);
- g_free (std_err);
-
g_free (user->password_hint);
user->password_hint = NULL;
@@ -1785,20 +1673,10 @@ user_change_password_mode_authorized_cb (Daemon *daemon,
argv[2] = user->user_name;
argv[3] = NULL;
- std_out = NULL;
- std_err = NULL;
error = NULL;
- if (!g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, &std_out, &std_err, &status, &error)) {
+ if (!spawn_with_login_uid (context, argv, &error)) {
throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
g_error_free (error);
- g_free (std_out);
- g_free (std_err);
- return;
- }
- if (WEXITSTATUS (status) != 0) {
- throw_error (context, ERROR_FAILED, "usermod returned an error: %s", std_err);
- g_free (std_out);
- g_free (std_err);
return;
}
@@ -1870,8 +1748,6 @@ user_change_password_authorized_cb (Daemon *daemon,
{
gchar **strings = data;
GError *error;
- gint status;
- gchar *std_out, *std_err;
gchar *argv[5];
sys_log (context,
@@ -1886,27 +1762,13 @@ user_change_password_authorized_cb (Daemon *daemon,
argv[3] = user->user_name;
argv[4] = NULL;
- std_out = NULL;
- std_err = NULL;
error = NULL;
- if (!g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, &std_out, &std_err, &status, &error)) {
+ if (!spawn_with_login_uid (context, argv, &error)) {
throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
g_error_free (error);
- g_free (std_out);
- g_free (std_err);
return;
}
- if (WEXITSTATUS (status) != 0) {
- throw_error (context, ERROR_FAILED, "usermod returned an error: %s", std_err);
- g_free (std_out);
- g_free (std_err);
- return;
- }
-
- g_free (std_out);
- g_free (std_err);
-
if (user->password_mode != PASSWORD_MODE_REGULAR) {
user->password_mode = PASSWORD_MODE_REGULAR;
g_object_notify (G_OBJECT (user), "password-mode");
diff --git a/src/util.c b/src/util.c
index e12c687..2cd2af8 100644
--- a/src/util.c
+++ b/src/util.c
@@ -21,7 +21,14 @@
#include "config.h"
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <wait.h>
+
#include <syslog.h>
+
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
@@ -142,3 +149,68 @@ sys_log (DBusGMethodInvocation *context,
g_free (real_format);
}
+
+static gint
+get_caller_uid (DBusGMethodInvocation *context)
+{
+ PolkitSubject *subject;
+ gchar *cmdline;
+ gint pid;
+ gint uid;
+
+ subject = polkit_system_bus_name_new (dbus_g_method_get_sender (context));
+ cmdline = _polkit_subject_get_cmdline (subject, &pid, &uid);
+
+ g_object_unref (subject);
+ g_free (cmdline);
+
+ return uid;
+}
+
+static void
+setup_loginuid (gpointer data)
+{
+ const char *id = data;
+ int fd;
+
+ fd = open ("/proc/self/loginuid", O_WRONLY);
+ write (fd, id, strlen (id));
+ close (fd);
+}
+
+gboolean
+spawn_with_login_uid (DBusGMethodInvocation *context,
+ gchar *argv[],
+ GError **error)
+{
+ GError *local_error;
+ gchar loginuid[20];
+ gchar *std_err;
+ gint status;
+
+ g_snprintf (loginuid, 20, "%d", get_caller_uid (context));
+
+ local_error = NULL;
+ std_err = NULL;
+
+ if (!g_spawn_sync (NULL, argv, NULL, 0, setup_loginuid, loginuid, NULL, &std_err, &status, &local_error)) {
+ g_propagate_error (error, local_error);
+ g_free (std_err);
+ return FALSE;
+ }
+
+ if (WEXITSTATUS (status) != 0) {
+ g_set_error (error,
+ G_SPAWN_ERROR,
+ G_SPAWN_ERROR_FAILED,
+ "%s returned an error (%d): %s",
+ argv[0], WEXITSTATUS(status), std_err);
+ g_free (std_err);
+ return FALSE;
+ }
+
+ g_free (std_err);
+
+ return TRUE;
+}
+
diff --git a/src/util.h b/src/util.h
index ff5e0df..3f51af1 100644
--- a/src/util.h
+++ b/src/util.h
@@ -31,6 +31,10 @@ void sys_log (DBusGMethodInvocation *context,
const gchar *format,
...);
+gboolean spawn_with_login_uid (DBusGMethodInvocation *context,
+ gchar *argv[],
+ GError **error);
+
G_END_DECLS
#endif /* __UTIL_H__ */