summaryrefslogtreecommitdiff
path: root/src/3rd_party/dbus-1.7.8/bus/activation-helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rd_party/dbus-1.7.8/bus/activation-helper.c')
-rw-r--r--src/3rd_party/dbus-1.7.8/bus/activation-helper.c549
1 files changed, 0 insertions, 549 deletions
diff --git a/src/3rd_party/dbus-1.7.8/bus/activation-helper.c b/src/3rd_party/dbus-1.7.8/bus/activation-helper.c
deleted file mode 100644
index 394f3938c1..0000000000
--- a/src/3rd_party/dbus-1.7.8/bus/activation-helper.c
+++ /dev/null
@@ -1,549 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-/* activation-helper.c Setuid helper for launching programs as a custom
- * user. This file is security sensitive.
- *
- * Copyright (C) 2007 Red Hat, Inc.
- *
- * Licensed under the Academic Free License version 2.1
- *
- * 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
- *
- */
-
-#include <config.h>
-
-#include "bus.h"
-#include "driver.h"
-#include "utils.h"
-#include "desktop-file.h"
-#include "config-parser-trivial.h"
-#include "activation-helper.h"
-#include "activation-exit-codes.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <pwd.h>
-#include <grp.h>
-
-#include <dbus/dbus-misc.h>
-#include <dbus/dbus-shell.h>
-#include <dbus/dbus-marshal-validate.h>
-
-static BusDesktopFile *
-desktop_file_for_name (BusConfigParser *parser,
- const char *name,
- DBusError *error)
-{
- BusDesktopFile *desktop_file;
- DBusList **service_dirs;
- DBusList *link;
- DBusError tmp_error;
- DBusString full_path;
- DBusString filename;
- const char *dir;
-
- _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-
- desktop_file = NULL;
-
- if (!_dbus_string_init (&filename))
- {
- BUS_SET_OOM (error);
- goto out_all;
- }
-
- if (!_dbus_string_init (&full_path))
- {
- BUS_SET_OOM (error);
- goto out_filename;
- }
-
- if (!_dbus_string_append (&filename, name) ||
- !_dbus_string_append (&filename, ".service"))
- {
- BUS_SET_OOM (error);
- goto out;
- }
-
- service_dirs = bus_config_parser_get_service_dirs (parser);
- for (link = _dbus_list_get_first_link (service_dirs);
- link != NULL;
- link = _dbus_list_get_next_link (service_dirs, link))
- {
- dir = link->data;
- _dbus_verbose ("Looking at '%s'\n", dir);
-
- dbus_error_init (&tmp_error);
-
- /* clear the path from last time */
- _dbus_string_set_length (&full_path, 0);
-
- /* build the full path */
- if (!_dbus_string_append (&full_path, dir) ||
- !_dbus_concat_dir_and_file (&full_path, &filename))
- {
- BUS_SET_OOM (error);
- goto out;
- }
-
- _dbus_verbose ("Trying to load file '%s'\n", _dbus_string_get_data (&full_path));
- desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
- if (desktop_file == NULL)
- {
- _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
- _dbus_verbose ("Could not load %s: %s: %s\n",
- _dbus_string_get_const_data (&full_path),
- tmp_error.name, tmp_error.message);
-
- /* we may have failed if the file is not found; this is not fatal */
- if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
- {
- dbus_move_error (&tmp_error, error);
- /* we only bail out on OOM */
- goto out;
- }
- dbus_error_free (&tmp_error);
- }
-
- /* did we find the desktop file we want? */
- if (desktop_file != NULL)
- break;
- }
-
- /* Didn't find desktop file; set error */
- if (desktop_file == NULL)
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,
- "The name %s was not provided by any .service files",
- name);
- }
-
-out:
- _dbus_string_free (&full_path);
-out_filename:
- _dbus_string_free (&filename);
-out_all:
- return desktop_file;
-}
-
-/* Clears the environment, except for DBUS_STARTER_x,
- * which we hardcode to the system bus.
- */
-static dbus_bool_t
-clear_environment (DBusError *error)
-{
-#ifndef ACTIVATION_LAUNCHER_TEST
- /* totally clear the environment */
- if (!_dbus_clearenv ())
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
- "could not clear environment\n");
- return FALSE;
- }
-
- /* Ensure the bus is set to system */
- dbus_setenv ("DBUS_STARTER_ADDRESS", DBUS_SYSTEM_BUS_DEFAULT_ADDRESS);
- dbus_setenv ("DBUS_STARTER_BUS_TYPE", "system");
-#endif
-
- return TRUE;
-}
-
-static dbus_bool_t
-check_permissions (const char *dbus_user, DBusError *error)
-{
-#ifndef ACTIVATION_LAUNCHER_TEST
- uid_t uid, euid;
- struct passwd *pw;
-
- pw = NULL;
- uid = 0;
- euid = 0;
-
- /* bail out unless the dbus user is invoking the helper */
- pw = getpwnam(dbus_user);
- if (!pw)
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
- "cannot find user '%s'", dbus_user);
- return FALSE;
- }
- uid = getuid();
- if (pw->pw_uid != uid)
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
- "not invoked from user '%s'", dbus_user);
- return FALSE;
- }
-
- /* bail out unless we are setuid to user root */
- euid = geteuid();
- if (euid != 0)
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
- "not setuid root");
- return FALSE;
- }
-#endif
-
- return TRUE;
-}
-
-static dbus_bool_t
-check_service_name (BusDesktopFile *desktop_file,
- const char *service_name,
- DBusError *error)
-{
- char *name_tmp;
- dbus_bool_t retval;
-
- retval = FALSE;
-
- /* try to get Name */
- if (!bus_desktop_file_get_string (desktop_file,
- DBUS_SERVICE_SECTION,
- DBUS_SERVICE_NAME,
- &name_tmp,
- error))
- goto failed;
-
- /* verify that the name is the same as the file service name */
- if (strcmp (service_name, name_tmp) != 0)
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_FILE_INVALID,
- "Service '%s' does not match expected value", name_tmp);
- goto failed_free;
- }
-
- retval = TRUE;
-
-failed_free:
- /* we don't return the name, so free it here */
- dbus_free (name_tmp);
-failed:
- return retval;
-}
-
-static dbus_bool_t
-get_parameters_for_service (BusDesktopFile *desktop_file,
- const char *service_name,
- char **exec,
- char **user,
- DBusError *error)
-{
- char *exec_tmp;
- char *user_tmp;
-
- exec_tmp = NULL;
- user_tmp = NULL;
-
- /* check the name of the service */
- if (!check_service_name (desktop_file, service_name, error))
- goto failed;
-
- /* get the complete path of the executable */
- if (!bus_desktop_file_get_string (desktop_file,
- DBUS_SERVICE_SECTION,
- DBUS_SERVICE_EXEC,
- &exec_tmp,
- error))
- {
- _DBUS_ASSERT_ERROR_IS_SET (error);
- goto failed;
- }
-
- /* get the user that should run this service - user is compulsary for system activation */
- if (!bus_desktop_file_get_string (desktop_file,
- DBUS_SERVICE_SECTION,
- DBUS_SERVICE_USER,
- &user_tmp,
- error))
- {
- _DBUS_ASSERT_ERROR_IS_SET (error);
- goto failed;
- }
-
- /* only assign if all the checks passed */
- *exec = exec_tmp;
- *user = user_tmp;
- return TRUE;
-
-failed:
- dbus_free (exec_tmp);
- dbus_free (user_tmp);
- return FALSE;
-}
-
-static dbus_bool_t
-switch_user (char *user, DBusError *error)
-{
-#ifndef ACTIVATION_LAUNCHER_TEST
- struct passwd *pw;
-
- /* find user */
- pw = getpwnam (user);
- if (!pw)
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
- "cannot find user '%s'\n", user);
- return FALSE;
- }
-
- /* initialize the group access list */
- if (initgroups (user, pw->pw_gid))
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
- "could not initialize groups");
- return FALSE;
- }
-
- /* change to the primary group for the user */
- if (setgid (pw->pw_gid))
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
- "cannot setgid group %i", pw->pw_gid);
- return FALSE;
- }
-
- /* change to the user specified */
- if (setuid (pw->pw_uid) < 0)
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
- "cannot setuid user %i", pw->pw_uid);
- return FALSE;
- }
-#endif
- return TRUE;
-}
-
-static dbus_bool_t
-exec_for_correct_user (char *exec, char *user, DBusError *error)
-{
- char **argv;
- int argc;
- dbus_bool_t retval;
-
- argc = 0;
- retval = TRUE;
- argv = NULL;
-
- if (!switch_user (user, error))
- return FALSE;
-
- /* convert command into arguments */
- if (!_dbus_shell_parse_argv (exec, &argc, &argv, error))
- return FALSE;
-
-#ifndef ACTIVATION_LAUNCHER_DO_OOM
- /* replace with new binary, with no environment */
- if (execv (argv[0], argv) < 0)
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
- "Failed to exec: %s", argv[0]);
- retval = FALSE;
- }
-#endif
-
- dbus_free_string_array (argv);
- return retval;
-}
-
-static dbus_bool_t
-check_bus_name (const char *bus_name,
- DBusError *error)
-{
- DBusString str;
-
- _dbus_string_init_const (&str, bus_name);
- if (!_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_INVALID,
- "bus name '%s' is not a valid bus name\n",
- bus_name);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static dbus_bool_t
-get_correct_parser (BusConfigParser **parser, DBusError *error)
-{
- DBusString config_file;
- dbus_bool_t retval;
-#ifdef ACTIVATION_LAUNCHER_TEST
- const char *test_config_file;
-#endif
-
- retval = FALSE;
-
-#ifdef ACTIVATION_LAUNCHER_TEST
- test_config_file = NULL;
-
- /* there is no _way_ we should be setuid if this define is set.
- * but we should be doubly paranoid and check... */
- if (getuid() != geteuid())
- _dbus_assert_not_reached ("dbus-daemon-launch-helper-test binary is setuid!");
-
- /* this is not a security hole. The environment variable is only passed in the
- * dbus-daemon-lauch-helper-test NON-SETUID launcher */
- test_config_file = _dbus_getenv ("TEST_LAUNCH_HELPER_CONFIG");
- if (test_config_file == NULL)
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
- "the TEST_LAUNCH_HELPER_CONFIG env variable is not set");
- goto out;
- }
-#endif
-
- /* we _only_ use the predefined system config file */
- if (!_dbus_string_init (&config_file))
- {
- BUS_SET_OOM (error);
- goto out;
- }
-#ifndef ACTIVATION_LAUNCHER_TEST
- if (!_dbus_string_append (&config_file, DBUS_SYSTEM_CONFIG_FILE))
- {
- BUS_SET_OOM (error);
- goto out_free_config;
- }
-#else
- if (!_dbus_string_append (&config_file, test_config_file))
- {
- BUS_SET_OOM (error);
- goto out_free_config;
- }
-#endif
-
- /* where are we pointing.... */
- _dbus_verbose ("dbus-daemon-activation-helper: using config file: %s\n",
- _dbus_string_get_const_data (&config_file));
-
- /* get the dbus user */
- *parser = bus_config_load (&config_file, TRUE, NULL, error);
- if (*parser == NULL)
- {
- goto out_free_config;
- }
-
- /* woot */
- retval = TRUE;
-
-out_free_config:
- _dbus_string_free (&config_file);
-out:
- return retval;
-}
-
-static dbus_bool_t
-launch_bus_name (const char *bus_name, BusConfigParser *parser, DBusError *error)
-{
- BusDesktopFile *desktop_file;
- char *exec, *user;
- dbus_bool_t retval;
-
- exec = NULL;
- user = NULL;
- retval = FALSE;
-
- /* get the correct service file for the name we are trying to activate */
- desktop_file = desktop_file_for_name (parser, bus_name, error);
- if (desktop_file == NULL)
- return FALSE;
-
- /* get exec and user for service name */
- if (!get_parameters_for_service (desktop_file, bus_name, &exec, &user, error))
- goto finish;
-
- _dbus_verbose ("dbus-daemon-activation-helper: Name='%s'\n", bus_name);
- _dbus_verbose ("dbus-daemon-activation-helper: Exec='%s'\n", exec);
- _dbus_verbose ("dbus-daemon-activation-helper: User='%s'\n", user);
-
- /* actually execute */
- if (!exec_for_correct_user (exec, user, error))
- goto finish;
-
- retval = TRUE;
-
-finish:
- dbus_free (exec);
- dbus_free (user);
- bus_desktop_file_free (desktop_file);
- return retval;
-}
-
-static dbus_bool_t
-check_dbus_user (BusConfigParser *parser, DBusError *error)
-{
- const char *dbus_user;
-
- dbus_user = bus_config_parser_get_user (parser);
- if (dbus_user == NULL)
- {
- dbus_set_error (error, DBUS_ERROR_SPAWN_CONFIG_INVALID,
- "could not get user from config file\n");
- return FALSE;
- }
-
- /* check to see if permissions are correct */
- if (!check_permissions (dbus_user, error))
- return FALSE;
-
- return TRUE;
-}
-
-dbus_bool_t
-run_launch_helper (const char *bus_name,
- DBusError *error)
-{
- BusConfigParser *parser;
- dbus_bool_t retval;
-
- parser = NULL;
- retval = FALSE;
-
- /* clear the environment, apart from a few select settings */
- if (!clear_environment (error))
- goto error;
-
- /* check to see if we have a valid bus name */
- if (!check_bus_name (bus_name, error))
- goto error;
-
- /* get the correct parser, either the test or default parser */
- if (!get_correct_parser (&parser, error))
- goto error;
-
- /* check we are being invoked by the correct dbus user */
- if (!check_dbus_user (parser, error))
- goto error_free_parser;
-
- /* launch the bus with the service defined user */
- if (!launch_bus_name (bus_name, parser, error))
- goto error_free_parser;
-
- /* woohoo! */
- retval = TRUE;
-
-error_free_parser:
- bus_config_parser_unref (parser);
-error:
- return retval;
-}
-