1f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes/* activation-helper.c  Setuid helper for launching programs as a custom
3f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes *                      user. This file is security sensitive.
4f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes *
5f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes * Copyright (C) 2007 Red Hat, Inc.
6f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes *
7f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes * Licensed under the Academic Free License version 2.1
8f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes *
9f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes * This program is free software; you can redistribute it and/or modify
10f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes * it under the terms of the GNU General Public License as published by
11f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes * the Free Software Foundation; either version 2 of the License, or
12f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes * (at your option) any later version.
13f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes *
14f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes * This program is distributed in the hope that it will be useful,
15f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes * but WITHOUT ANY WARRANTY; without even the implied warranty of
16f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes * GNU General Public License for more details.
18f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes *
19f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes * You should have received a copy of the GNU General Public License
20f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes * along with this program; if not, write to the Free Software
215baf2f856a9c6625993234855b07680da1c8916fTobias Mueller * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes *
23f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes */
24f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
25f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include <config.h>
26f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
27f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include "bus.h"
28f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include "driver.h"
29f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include "utils.h"
30f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include "desktop-file.h"
31f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include "config-parser-trivial.h"
32f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include "activation-helper.h"
33f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include "activation-exit-codes.h"
34f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
35f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include <stdio.h>
36f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include <stdlib.h>
37f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include <string.h>
38f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include <unistd.h>
39f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include <sys/types.h>
40f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include <pwd.h>
41f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include <grp.h>
42f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
43f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include <dbus/dbus-shell.h>
44f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#include <dbus/dbus-marshal-validate.h>
45f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
46f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesstatic BusDesktopFile *
47f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesdesktop_file_for_name (BusConfigParser *parser,
48f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                       const char *name,
49f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                       DBusError  *error)
50f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes{
51f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  BusDesktopFile *desktop_file;
52f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  DBusList **service_dirs;
53f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  DBusList *link;
54f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  DBusError tmp_error;
55f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  DBusString full_path;
56f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  DBusString filename;
57f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  const char *dir;
58f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
59f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
60f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
61f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  desktop_file = NULL;
62f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
63f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!_dbus_string_init (&filename))
64f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
65f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      BUS_SET_OOM (error);
66f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      goto out_all;
67f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
68f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
69f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!_dbus_string_init (&full_path))
70f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
71f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      BUS_SET_OOM (error);
72f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      goto out_filename;
73f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
74f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
75f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!_dbus_string_append (&filename, name) ||
76f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      !_dbus_string_append (&filename, ".service"))
77f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
78f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      BUS_SET_OOM (error);
79f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      goto out;
80f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
81f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
82f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  service_dirs = bus_config_parser_get_service_dirs (parser);
83f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  for (link = _dbus_list_get_first_link (service_dirs);
84f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes       link != NULL;
85f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes       link = _dbus_list_get_next_link (service_dirs, link))
86f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
87f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dir = link->data;
88f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      _dbus_verbose ("Looking at '%s'\n", dir);
89f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
90f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_error_init (&tmp_error);
91f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
92f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      /* clear the path from last time */
93f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      _dbus_string_set_length (&full_path, 0);
94f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
95f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      /* build the full path */
96f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      if (!_dbus_string_append (&full_path, dir) ||
97f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes          !_dbus_concat_dir_and_file (&full_path, &filename))
98f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes        {
99f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes          BUS_SET_OOM (error);
100f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes          goto out;
101f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes        }
102f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
103f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      _dbus_verbose ("Trying to load file '%s'\n", _dbus_string_get_data (&full_path));
104f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
105f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      if (desktop_file == NULL)
106f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes        {
107f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes          _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
108f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes          _dbus_verbose ("Could not load %s: %s: %s\n",
109f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                         _dbus_string_get_const_data (&full_path),
110f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                         tmp_error.name, tmp_error.message);
111f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
112f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes          /* we may have failed if the file is not found; this is not fatal */
113f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes          if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
114f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes            {
115f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes              dbus_move_error (&tmp_error, error);
116f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes              /* we only bail out on OOM */
117f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes              goto out;
118f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes            }
119f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes          dbus_error_free (&tmp_error);
120f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes        }
121f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
122f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      /* did we find the desktop file we want? */
123f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      if (desktop_file != NULL)
124f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes        break;
125f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
126f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
127f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* Didn't find desktop file; set error */
128f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (desktop_file == NULL)
129f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
130f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,
131f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      "The name %s was not provided by any .service files",
132f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      name);
133f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
134f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
135f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesout:
136f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  _dbus_string_free (&full_path);
137f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesout_filename:
138f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  _dbus_string_free (&filename);
139f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesout_all:
140f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  return desktop_file;
141f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes}
142f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
1434299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat/* Clears the environment, except for DBUS_STARTER_x,
1444299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat * which we hardcode to the system bus.
1454299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat */
146f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesstatic dbus_bool_t
147f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesclear_environment (DBusError *error)
148f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes{
149f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#ifndef ACTIVATION_LAUNCHER_TEST
150f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* totally clear the environment */
151f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!_dbus_clearenv ())
152f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
153f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
154f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      "could not clear environment\n");
155f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      return FALSE;
156f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
157f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#endif
158f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
1594299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  /* Ensure the bus is set to system */
1604299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  _dbus_setenv ("DBUS_STARTER_ADDRESS", DBUS_SYSTEM_BUS_DEFAULT_ADDRESS);
161f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  _dbus_setenv ("DBUS_STARTER_BUS_TYPE", "system");
162f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
163f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  return TRUE;
164f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes}
165f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
166f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesstatic dbus_bool_t
167f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughescheck_permissions (const char *dbus_user, DBusError *error)
168f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes{
1694299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat#ifndef ACTIVATION_LAUNCHER_TEST
170f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  uid_t uid, euid;
171f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  struct passwd *pw;
172f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
173f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  pw = NULL;
174f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  uid = 0;
175f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  euid = 0;
176f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
177f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* bail out unless the dbus user is invoking the helper */
178f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  pw = getpwnam(dbus_user);
179f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!pw)
180f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
181f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
182f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      "cannot find user '%s'", dbus_user);
183f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      return FALSE;
184f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
185f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  uid = getuid();
186f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (pw->pw_uid != uid)
187f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
188f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
189f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      "not invoked from user '%s'", dbus_user);
190f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      return FALSE;
191f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
192f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
193f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* bail out unless we are setuid to user root */
194f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  euid = geteuid();
195f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (euid != 0)
196f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
197f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
198f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      "not setuid root");
199f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      return FALSE;
200f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
201f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#endif
202f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
203f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  return TRUE;
204f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes}
205f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
206f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesstatic dbus_bool_t
207f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughescheck_service_name (BusDesktopFile *desktop_file,
208f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                    const char     *service_name,
209f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                    DBusError      *error)
210f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes{
211f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  char *name_tmp;
212f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  dbus_bool_t retval;
213f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
214f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  retval = FALSE;
215f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
216f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* try to get Name */
217f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!bus_desktop_file_get_string (desktop_file,
218f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                                    DBUS_SERVICE_SECTION,
219f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                                    DBUS_SERVICE_NAME,
220f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                                    &name_tmp,
221f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                                    error))
222f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    goto failed;
223f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
224f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* verify that the name is the same as the file service name */
225f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (strcmp (service_name, name_tmp) != 0)
226f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
227f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_FILE_INVALID,
228f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      "Service '%s' does not match expected value", name_tmp);
229f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      goto failed_free;
230f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
231f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
232f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  retval = TRUE;
233f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
234f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesfailed_free:
235f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* we don't return the name, so free it here */
236f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  dbus_free (name_tmp);
237f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesfailed:
238f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  return retval;
239f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes}
240f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
241f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesstatic dbus_bool_t
242f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesget_parameters_for_service (BusDesktopFile *desktop_file,
243f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                            const char     *service_name,
244f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                            char          **exec,
245f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                            char          **user,
246f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                            DBusError      *error)
247f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes{
248f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  char *exec_tmp;
249f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  char *user_tmp;
250f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
251f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  exec_tmp = NULL;
252f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  user_tmp = NULL;
253f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
254f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* check the name of the service */
255f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!check_service_name (desktop_file, service_name, error))
256f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    goto failed;
257f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
258f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* get the complete path of the executable */
259f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!bus_desktop_file_get_string (desktop_file,
260f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                                    DBUS_SERVICE_SECTION,
261f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                                    DBUS_SERVICE_EXEC,
262f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                                    &exec_tmp,
263f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                                    error))
264f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
265f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      _DBUS_ASSERT_ERROR_IS_SET (error);
266f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      goto failed;
267f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
268f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
269f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* get the user that should run this service - user is compulsary for system activation */
270f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!bus_desktop_file_get_string (desktop_file,
271f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                                    DBUS_SERVICE_SECTION,
272f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                                    DBUS_SERVICE_USER,
273f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                                    &user_tmp,
274f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                                    error))
275f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
276f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      _DBUS_ASSERT_ERROR_IS_SET (error);
277f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      goto failed;
278f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
279f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
280f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* only assign if all the checks passed */
281f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  *exec = exec_tmp;
282f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  *user = user_tmp;
283f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  return TRUE;
284f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
285f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesfailed:
286f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  dbus_free (exec_tmp);
287f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  dbus_free (user_tmp);
288f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  return FALSE;
289f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes}
290f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
291f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesstatic dbus_bool_t
292f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesswitch_user (char *user, DBusError *error)
293f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes{
294f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#ifndef ACTIVATION_LAUNCHER_TEST
295f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  struct passwd *pw;
296f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
297f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* find user */
298f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  pw = getpwnam (user);
299f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!pw)
300f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
301f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
302f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      "cannot find user '%s'\n", user);
303f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      return FALSE;
304f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
305f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
306f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* initialize the group access list */
307f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (initgroups (user, pw->pw_gid))
308f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
309f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
310f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      "could not initialize groups");
311f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      return FALSE;
312f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
313f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
314f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* change to the primary group for the user */
315f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (setgid (pw->pw_gid))
316f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
317f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
318f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      "cannot setgid group %i", pw->pw_gid);
319f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      return FALSE;
320f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
321f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
322f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* change to the user specified */
323f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (setuid (pw->pw_uid) < 0)
324f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
325f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
326f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      "cannot setuid user %i", pw->pw_uid);
327f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      return FALSE;
328f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
329f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#endif
330f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  return TRUE;
331f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes}
332f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
333f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesstatic dbus_bool_t
334f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesexec_for_correct_user (char *exec, char *user, DBusError *error)
335f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes{
336f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  char **argv;
337f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  int argc;
338f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  dbus_bool_t retval;
339f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
340f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  argc = 0;
341f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  retval = TRUE;
342f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  argv = NULL;
343f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
344f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!switch_user (user, error))
345f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    return FALSE;
346f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
347f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* convert command into arguments */
348f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!_dbus_shell_parse_argv (exec, &argc, &argv, error))
349f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    return FALSE;
350f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
351f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#ifndef ACTIVATION_LAUNCHER_DO_OOM
352f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* replace with new binary, with no environment */
353f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (execv (argv[0], argv) < 0)
354f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
355f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
356f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      "Failed to exec: %s", argv[0]);
357f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      retval = FALSE;
358f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
359f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#endif
360f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
361f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  dbus_free_string_array (argv);
362f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  return retval;
363f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes}
364f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
365f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesstatic dbus_bool_t
366ae4a1586969aaca534508837830d7d3de4ade070Havoc Penningtoncheck_bus_name (const char *bus_name,
367ae4a1586969aaca534508837830d7d3de4ade070Havoc Pennington                DBusError  *error)
368f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes{
369ae4a1586969aaca534508837830d7d3de4ade070Havoc Pennington  DBusString str;
370ae4a1586969aaca534508837830d7d3de4ade070Havoc Pennington
371ae4a1586969aaca534508837830d7d3de4ade070Havoc Pennington  _dbus_string_init_const (&str, bus_name);
372ae4a1586969aaca534508837830d7d3de4ade070Havoc Pennington  if (!_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
373f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
374f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,
375ae4a1586969aaca534508837830d7d3de4ade070Havoc Pennington                      "bus name '%s' is not a valid bus name\n",
376ae4a1586969aaca534508837830d7d3de4ade070Havoc Pennington                      bus_name);
377f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      return FALSE;
378f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
379ae4a1586969aaca534508837830d7d3de4ade070Havoc Pennington
380f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  return TRUE;
381f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes}
382f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
383f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesstatic dbus_bool_t
384f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesget_correct_parser (BusConfigParser **parser, DBusError *error)
385f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes{
386f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  DBusString config_file;
387f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  dbus_bool_t retval;
3884299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat#ifdef ACTIVATION_LAUNCHER_TEST
389f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  const char *test_config_file;
3904299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat#endif
391f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
392f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  retval = FALSE;
393f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
394f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#ifdef ACTIVATION_LAUNCHER_TEST
3954299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  test_config_file = NULL;
3964299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
397f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* there is no _way_ we should be setuid if this define is set.
398f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes   * but we should be doubly paranoid and check... */
399f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (getuid() != geteuid())
400f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    _dbus_assert_not_reached ("dbus-daemon-launch-helper-test binary is setuid!");
401f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
402f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* this is not a security hole. The environment variable is only passed in the
403f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes   * dbus-daemon-lauch-helper-test NON-SETUID launcher */
404f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  test_config_file = _dbus_getenv ("TEST_LAUNCH_HELPER_CONFIG");
405f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (test_config_file == NULL)
406f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
407f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
408f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      "the TEST_LAUNCH_HELPER_CONFIG env variable is not set");
409f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      goto out;
410f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
411f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#endif
412f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
413f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* we _only_ use the predefined system config file */
414f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!_dbus_string_init (&config_file))
415f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
416f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      BUS_SET_OOM (error);
417f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      goto out;
418f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
419f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#ifndef ACTIVATION_LAUNCHER_TEST
420f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!_dbus_string_append (&config_file, DBUS_SYSTEM_CONFIG_FILE))
421f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
422f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      BUS_SET_OOM (error);
423f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      goto out_free_config;
424f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
425f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#else
426f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!_dbus_string_append (&config_file, test_config_file))
427f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
428f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      BUS_SET_OOM (error);
429f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      goto out_free_config;
430f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
431f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes#endif
432f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
433f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* where are we pointing.... */
434f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  _dbus_verbose ("dbus-daemon-activation-helper: using config file: %s\n",
435f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                 _dbus_string_get_const_data (&config_file));
436f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
437f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* get the dbus user */
438f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  *parser = bus_config_load (&config_file, TRUE, NULL, error);
439f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (*parser == NULL)
440f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
441f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      goto out_free_config;
442f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
443f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
444f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* woot */
445f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  retval = TRUE;
446f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
447f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesout_free_config:
448f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  _dbus_string_free (&config_file);
449f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesout:
450f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  return retval;
451f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes}
452f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
453f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesstatic dbus_bool_t
454f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hugheslaunch_bus_name (const char *bus_name, BusConfigParser *parser, DBusError *error)
455f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes{
456f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  BusDesktopFile *desktop_file;
457f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  char *exec, *user;
458f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  dbus_bool_t retval;
459f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
460f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  exec = NULL;
461f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  user = NULL;
462f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  retval = FALSE;
463f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
464f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* get the correct service file for the name we are trying to activate */
465f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  desktop_file = desktop_file_for_name (parser, bus_name, error);
466f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (desktop_file == NULL)
467f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    return FALSE;
468f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
469f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* get exec and user for service name */
470f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!get_parameters_for_service (desktop_file, bus_name, &exec, &user, error))
471f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    goto finish;
472f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
473f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  _dbus_verbose ("dbus-daemon-activation-helper: Name='%s'\n", bus_name);
474f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  _dbus_verbose ("dbus-daemon-activation-helper: Exec='%s'\n", exec);
475f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  _dbus_verbose ("dbus-daemon-activation-helper: User='%s'\n", user);
476f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
477f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* actually execute */
478f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!exec_for_correct_user (exec, user, error))
479f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    goto finish;
480f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
481f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  retval = TRUE;
482f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
483f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesfinish:
484f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  dbus_free (exec);
485f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  dbus_free (user);
486f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  bus_desktop_file_free (desktop_file);
487f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  return retval;
488f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes}
489f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
490f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesstatic dbus_bool_t
491f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughescheck_dbus_user (BusConfigParser *parser, DBusError *error)
492f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes{
493f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  const char *dbus_user;
494f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
495f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  dbus_user = bus_config_parser_get_user (parser);
496f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (dbus_user == NULL)
497f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    {
498f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      dbus_set_error (error, DBUS_ERROR_SPAWN_CONFIG_INVALID,
499f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes                      "could not get user from config file\n");
500f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes      return FALSE;
501f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    }
502f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
503f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* check to see if permissions are correct */
504f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!check_permissions (dbus_user, error))
505f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    return FALSE;
506f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
507f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  return TRUE;
508f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes}
509f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
510f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughesdbus_bool_t
511ae4a1586969aaca534508837830d7d3de4ade070Havoc Penningtonrun_launch_helper (const char *bus_name,
512ae4a1586969aaca534508837830d7d3de4ade070Havoc Pennington                   DBusError  *error)
513f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes{
514f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  BusConfigParser *parser;
515f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  dbus_bool_t retval;
516f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
517f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  parser = NULL;
518f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  retval = FALSE;
519f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
520f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* clear the environment, apart from a few select settings */
521f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!clear_environment (error))
522f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    goto error;
523f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
524f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* check to see if we have a valid bus name */
525f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!check_bus_name (bus_name, error))
526f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    goto error;
527f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
528f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* get the correct parser, either the test or default parser */
529f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!get_correct_parser (&parser, error))
530f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    goto error;
531f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
532f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* check we are being invoked by the correct dbus user */
533f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!check_dbus_user (parser, error))
534f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    goto error_free_parser;
535f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
536f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* launch the bus with the service defined user */
537f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  if (!launch_bus_name (bus_name, parser, error))
538f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes    goto error_free_parser;
539f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
540f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  /* woohoo! */
541f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  retval = TRUE;
542f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
543f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hugheserror_free_parser:
544f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  bus_config_parser_unref (parser);
545f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hugheserror:
546f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes  return retval;
547f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes}
548f4082146e91014c56c6215fb4e471f9f1baa8f60Richard Hughes
549