]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/dbus-common.c
gnome-ask-password-agent.vala: check for VALA_0_12
[thirdparty/systemd.git] / src / dbus-common.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
9a1ac7b9
LP
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <assert.h>
23#include <sys/socket.h>
24#include <errno.h>
25#include <unistd.h>
26#include <dbus/dbus.h>
27
28#include "log.h"
29#include "dbus-common.h"
b9978121 30#include "util.h"
9a1ac7b9
LP
31
32int bus_check_peercred(DBusConnection *c) {
33 int fd;
34 struct ucred ucred;
35 socklen_t l;
36
37 assert(c);
38
39 assert_se(dbus_connection_get_unix_fd(c, &fd));
40
41 l = sizeof(struct ucred);
42 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0) {
43 log_error("SO_PEERCRED failed: %m");
44 return -errno;
45 }
46
47 if (l != sizeof(struct ucred)) {
48 log_error("SO_PEERCRED returned wrong size.");
49 return -E2BIG;
50 }
51
52 if (ucred.uid != 0)
53 return -EPERM;
54
55 return 1;
56}
57
f4579ce7 58int bus_connect(DBusBusType t, DBusConnection **_bus, bool *private, DBusError *error) {
9a1ac7b9
LP
59 DBusConnection *bus;
60
61 assert(_bus);
62
b9978121
LP
63#define TIMEOUT_USEC (60*USEC_PER_SEC)
64
9a1ac7b9
LP
65 /* If we are root, then let's not go via the bus */
66 if (geteuid() == 0 && t == DBUS_BUS_SYSTEM) {
b9978121 67 usec_t begin, tstamp;
9a1ac7b9 68
b574246b 69 if (!(bus = dbus_connection_open_private("unix:abstract=/org/freedesktop/systemd1/private", error)))
9a1ac7b9
LP
70 return -EIO;
71
72 if (bus_check_peercred(bus) < 0) {
b9978121 73 dbus_connection_close(bus);
9a1ac7b9
LP
74 dbus_connection_unref(bus);
75
76 dbus_set_error_const(error, DBUS_ERROR_ACCESS_DENIED, "Failed to verify owner of bus.");
77 return -EACCES;
78 }
f4579ce7 79
720ce21d
LP
80 /* This complexity should probably move into D-Bus itself:
81 *
82 * https://bugs.freedesktop.org/show_bug.cgi?id=35189 */
b9978121
LP
83 begin = tstamp = now(CLOCK_MONOTONIC);
84 for (;;) {
85
86 if (tstamp > begin + TIMEOUT_USEC)
87 break;
88
89 if (dbus_connection_get_is_authenticated(bus))
90 break;
91
92 if (!dbus_connection_read_write_dispatch(bus, ((begin + TIMEOUT_USEC - tstamp) + USEC_PER_MSEC - 1) / USEC_PER_MSEC))
93 break;
94
95 tstamp = now(CLOCK_MONOTONIC);
96 }
97
98 if (!dbus_connection_get_is_connected(bus)) {
99 dbus_connection_close(bus);
100 dbus_connection_unref(bus);
101
102 dbus_set_error_const(error, DBUS_ERROR_NO_SERVER, "Connection terminated during authentication.");
103 return -ECONNREFUSED;
104 }
105
106 if (!dbus_connection_get_is_authenticated(bus)) {
107 dbus_connection_close(bus);
108 dbus_connection_unref(bus);
109
110 dbus_set_error_const(error, DBUS_ERROR_TIMEOUT, "Failed to authenticate in time.");
111 return -EACCES;
112 }
113
f4579ce7
LP
114 if (private)
115 *private = true;
116
9a1ac7b9 117 } else {
51bc5d4b 118 if (!(bus = dbus_bus_get_private(t, error)))
9a1ac7b9 119 return -EIO;
f4579ce7
LP
120
121 if (private)
122 *private = false;
9a1ac7b9
LP
123 }
124
125 dbus_connection_set_exit_on_disconnect(bus, FALSE);
126
127 *_bus = bus;
128 return 0;
129}
4cf5d675
LP
130
131const char *bus_error_message(const DBusError *error) {
132 assert(error);
133
134 /* Sometimes the D-Bus server is a little bit too verbose with
135 * its error messages, so let's override them here */
136 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED))
137 return "Access denied";
138
139 return error->message;
140}