3
* session.c - session segregation
5
* Copyright © 2010,2011 Canonical Ltd.
6
* Author: Scott James Remnant <scott@netsplit.com>.
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License version 2, as
10
* published by the Free Software Foundation.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License along
18
* with this program; if not, write to the Free Software Foundation, Inc.,
19
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
#endif /* HAVE_CONFIG_H */
27
#include <dbus/dbus.h>
29
#include <sys/types.h>
37
#include <nih/macros.h>
38
#include <nih/alloc.h>
40
#include <nih/string.h>
41
#include <nih/logging.h>
42
#include <nih/error.h>
44
#include <nih-dbus/dbus_message.h>
54
* This list holds the list of known sessions; each item is a Session
57
NihList *sessions = NULL;
62
* If TRUE, disable user and chroot sessions, resulting in a
63
* "traditional" (pre-session support) system.
65
int disable_sessions = FALSE;
68
/* Prototypes for static functions */
69
static void session_create_conf_source (Session *sesson);
75
* Initialise the sessions list.
81
sessions = NIH_MUST (nih_list_new (NULL));
86
session_new (const void *parent,
92
nih_assert ((chroot != NULL) || (user != 0));
96
session = nih_new (parent, Session);
100
nih_list_init (&session->entry);
103
session->chroot = nih_strdup (session, chroot);
104
if (! session->chroot) {
109
session->chroot = NULL;
112
session->user = user;
114
session->conf_path = NULL;
116
nih_alloc_set_destructor (session, nih_list_destroy);
118
nih_list_add (sessions, &session->entry);
124
session_from_dbus (const void *parent,
125
NihDBusMessage *message)
128
DBusError dbus_error;
129
unsigned long unix_user;
130
unsigned long unix_process_id;
134
nih_assert (message != NULL);
136
/* Handle explicit command-line request and alternative request
137
* method (primarily for test framework) to disable session support.
139
if (disable_sessions || getenv ("UPSTART_NO_SESSIONS"))
144
/* Ask D-Bus nicely for the origin uid and/or pid of the caller;
145
* sadly we can't ask the bus daemon for the origin pid, so that
146
* one will just have to stay user-session only.
148
dbus_error_init (&dbus_error);
150
sender = dbus_message_get_sender (message->message);
152
unix_user = dbus_bus_get_unix_user (message->connection, sender,
154
if (unix_user == (unsigned long)-1) {
155
dbus_error_free (&dbus_error);
162
if (! dbus_connection_get_unix_user (message->connection,
166
if (! dbus_connection_get_unix_process_id (message->connection,
171
/* If we retrieved a process id, look up the root path for it;
172
* if it's just '/' don't worry so much about it.
174
if (unix_process_id) {
175
nih_local char *symlink = NULL;
178
symlink = NIH_MUST (nih_sprintf (NULL, "/proc/%lu/root",
180
len = readlink (symlink, root, sizeof root);
186
if (! strcmp (root, "/")) {
192
} else if (! unix_user) {
193
/* No process id or user id found, return the NULL session */
198
/* Now find in the existing Sessions list */
199
NIH_LIST_FOREACH (sessions, iter) {
200
Session *session = (Session *)iter;
202
if (unix_process_id) {
203
if (! session->chroot)
206
/* ignore sessions relating to other chroots */
207
if (strcmp (session->chroot, root))
211
/* ignore sessions relating to other users */
212
if (unix_user != session->user)
215
if (! session->conf_path)
216
session_create_conf_source (session);
222
/* Didn't find one, make a new one */
223
session = NIH_MUST (session_new (parent, unix_process_id ? root : NULL,
225
session_create_conf_source (session);
231
session_create_conf_source (Session *session)
235
nih_assert (session != NULL);
236
nih_assert (session->conf_path == NULL);
239
session->conf_path = NIH_MUST (nih_strdup (NULL, session->chroot));
243
pwd = getpwuid (session->user);
245
nih_error ("%d: %s: %s", session->user,
246
_("Unable to lookup home directory"),
249
nih_free (session->conf_path);
250
session->conf_path = NULL;
254
NIH_MUST (nih_strcat_sprintf (&session->conf_path, NULL, "%s/%s",
255
pwd->pw_dir, USERCONFDIR));
257
NIH_MUST (nih_strcat (&session->conf_path, NULL, CONFDIR));
260
source = NIH_MUST (conf_source_new (session, session->conf_path,
262
source->session = session;
264
if (conf_source_reload (source) < 0) {
267
err = nih_error_get ();
268
if (err->number != ENOENT)
269
nih_error ("%s: %s: %s", source->path,
270
_("Unable to load configuration"),
275
nih_free (session->conf_path);
276
session->conf_path = NULL;