1 /* GDBus - GLib D-Bus Library
2 *
3 * Copyright (C) 2008-2010 Red Hat, Inc.
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library 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 GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 *
20 * Author: David Zeuthen <davidz@redhat.com>
21 */
22
23 #include "config.h"
24
25 #include "gdbusauthobserver.h"
26 #include "gcredentials.h"
27 #include "gioenumtypes.h"
28 #include "giostream.h"
29 #include "gdbusprivate.h"
30
31 #include "glibintl.h"
32 #include "gmarshal-internal.h"
33
34 /**
35 * GDBusAuthObserver:
36 *
37 * `GDBusAuthObserver` provides a mechanism for participating
38 * in how a [class@Gio.DBusServer] (or a [class@Gio.DBusConnection])
39 * authenticates remote peers.
40 *
41 * Simply instantiate a `GDBusAuthObserver` and connect to the
42 * signals you are interested in. Note that new signals may be added
43 * in the future.
44 *
45 * ## Controlling Authentication Mechanisms
46 *
47 * By default, a `GDBusServer` or server-side `GDBusConnection` will allow
48 * any authentication mechanism to be used. If you only want to allow D-Bus
49 * connections with the `EXTERNAL` mechanism, which makes use of credentials
50 * passing and is the recommended mechanism for modern Unix platforms such
51 * as Linux and the BSD family, you would use a signal handler like this:
52 *
53 * ```c
54 * static gboolean
55 * on_allow_mechanism (GDBusAuthObserver *observer,
56 * const gchar *mechanism,
57 * gpointer user_data)
58 * {
59 * if (g_strcmp0 (mechanism, "EXTERNAL") == 0)
60 * {
61 * return TRUE;
62 * }
63 *
64 * return FALSE;
65 * }
66 * ```
67 *
68 * ## Controlling Authorization
69 *
70 * By default, a `GDBusServer` or server-side `GDBusConnection` will accept
71 * connections from any successfully authenticated user (but not from
72 * anonymous connections using the `ANONYMOUS` mechanism). If you only
73 * want to allow D-Bus connections from processes owned by the same uid
74 * as the server, since GLib 2.68, you should use the
75 * `G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER` flag. It’s equivalent
76 * to the following signal handler:
77 *
78 * ```c
79 * static gboolean
80 * on_authorize_authenticated_peer (GDBusAuthObserver *observer,
81 * GIOStream *stream,
82 * GCredentials *credentials,
83 * gpointer user_data)
84 * {
85 * gboolean authorized;
86 *
87 * authorized = FALSE;
88 * if (credentials != NULL)
89 * {
90 * GCredentials *own_credentials;
91 * own_credentials = g_credentials_new ();
92 * if (g_credentials_is_same_user (credentials, own_credentials, NULL))
93 * authorized = TRUE;
94 * g_object_unref (own_credentials);
95 * }
96 *
97 * return authorized;
98 * }
99 * ```
100 *
101 * Since: 2.26
102 */
103
104 typedef struct _GDBusAuthObserverClass GDBusAuthObserverClass;
105
106 /**
107 * GDBusAuthObserverClass:
108 * @authorize_authenticated_peer: Signal class handler for the #GDBusAuthObserver::authorize-authenticated-peer signal.
109 *
110 * Class structure for #GDBusAuthObserverClass.
111 *
112 * Since: 2.26
113 */
114 struct _GDBusAuthObserverClass
115 {
116 /*< private >*/
117 GObjectClass parent_class;
118
119 /*< public >*/
120
121 /* Signals */
122 gboolean (*authorize_authenticated_peer) (GDBusAuthObserver *observer,
123 GIOStream *stream,
124 GCredentials *credentials);
125
126 gboolean (*allow_mechanism) (GDBusAuthObserver *observer,
127 const gchar *mechanism);
128 };
129
130 struct _GDBusAuthObserver
131 {
132 GObject parent_instance;
133 };
134
135 enum
136 {
137 AUTHORIZE_AUTHENTICATED_PEER_SIGNAL,
138 ALLOW_MECHANISM_SIGNAL,
139 LAST_SIGNAL,
140 };
141
142 static guint signals[LAST_SIGNAL] = { 0 };
143
144 G_DEFINE_TYPE (GDBusAuthObserver, g_dbus_auth_observer, G_TYPE_OBJECT)
145
146 /* ---------------------------------------------------------------------------------------------------- */
147
148 static void
149 g_dbus_auth_observer_finalize (GObject *object)
150 {
151 G_OBJECT_CLASS (g_dbus_auth_observer_parent_class)->finalize (object);
152 }
153
154 static gboolean
155 g_dbus_auth_observer_authorize_authenticated_peer_real (GDBusAuthObserver *observer,
156 GIOStream *stream,
157 GCredentials *credentials)
158 {
159 return TRUE;
160 }
161
162 static gboolean
163 g_dbus_auth_observer_allow_mechanism_real (GDBusAuthObserver *observer,
164 const gchar *mechanism)
165 {
166 return TRUE;
167 }
168
169 static void
170 g_dbus_auth_observer_class_init (GDBusAuthObserverClass *klass)
171 {
172 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
173
174 gobject_class->finalize = g_dbus_auth_observer_finalize;
175
176 klass->authorize_authenticated_peer = g_dbus_auth_observer_authorize_authenticated_peer_real;
177 klass->allow_mechanism = g_dbus_auth_observer_allow_mechanism_real;
178
179 /**
180 * GDBusAuthObserver::authorize-authenticated-peer:
181 * @observer: The #GDBusAuthObserver emitting the signal.
182 * @stream: A #GIOStream for the #GDBusConnection.
183 * @credentials: (nullable): Credentials received from the peer or %NULL.
184 *
185 * Emitted to check if a peer that is successfully authenticated
186 * is authorized.
187 *
188 * Returns: %TRUE if the peer is authorized, %FALSE if not.
189 *
190 * Since: 2.26
191 */
192 signals[AUTHORIZE_AUTHENTICATED_PEER_SIGNAL] =
193 g_signal_new (I_("authorize-authenticated-peer"),
194 G_TYPE_DBUS_AUTH_OBSERVER,
195 G_SIGNAL_RUN_LAST,
196 G_STRUCT_OFFSET (GDBusAuthObserverClass, authorize_authenticated_peer),
197 _g_signal_accumulator_false_handled,
198 NULL, /* accu_data */
199 _g_cclosure_marshal_BOOLEAN__OBJECT_OBJECT,
200 G_TYPE_BOOLEAN,
201 2,
202 G_TYPE_IO_STREAM,
203 G_TYPE_CREDENTIALS);
204 g_signal_set_va_marshaller (signals[AUTHORIZE_AUTHENTICATED_PEER_SIGNAL],
205 G_TYPE_FROM_CLASS (klass),
206 _g_cclosure_marshal_BOOLEAN__OBJECT_OBJECTv);
207
208 /**
209 * GDBusAuthObserver::allow-mechanism:
210 * @observer: The #GDBusAuthObserver emitting the signal.
211 * @mechanism: The name of the mechanism, e.g. `DBUS_COOKIE_SHA1`.
212 *
213 * Emitted to check if @mechanism is allowed to be used.
214 *
215 * Returns: %TRUE if @mechanism can be used to authenticate the other peer, %FALSE if not.
216 *
217 * Since: 2.34
218 */
219 signals[ALLOW_MECHANISM_SIGNAL] =
220 g_signal_new (I_("allow-mechanism"),
221 G_TYPE_DBUS_AUTH_OBSERVER,
222 G_SIGNAL_RUN_LAST,
223 G_STRUCT_OFFSET (GDBusAuthObserverClass, allow_mechanism),
224 _g_signal_accumulator_false_handled,
225 NULL, /* accu_data */
226 _g_cclosure_marshal_BOOLEAN__STRING,
227 G_TYPE_BOOLEAN,
228 1,
229 G_TYPE_STRING);
230 g_signal_set_va_marshaller (signals[ALLOW_MECHANISM_SIGNAL],
231 G_TYPE_FROM_CLASS (klass),
232 _g_cclosure_marshal_BOOLEAN__STRINGv);
233 }
234
235 static void
236 g_dbus_auth_observer_init (GDBusAuthObserver *observer)
237 {
238 }
239
240 /**
241 * g_dbus_auth_observer_new:
242 *
243 * Creates a new #GDBusAuthObserver object.
244 *
245 * Returns: A #GDBusAuthObserver. Free with g_object_unref().
246 *
247 * Since: 2.26
248 */
249 GDBusAuthObserver *
250 g_dbus_auth_observer_new (void)
251 {
252 return g_object_new (G_TYPE_DBUS_AUTH_OBSERVER, NULL);
253 }
254
255 /* ---------------------------------------------------------------------------------------------------- */
256
257 /**
258 * g_dbus_auth_observer_authorize_authenticated_peer:
259 * @observer: A #GDBusAuthObserver.
260 * @stream: A #GIOStream for the #GDBusConnection.
261 * @credentials: (nullable): Credentials received from the peer or %NULL.
262 *
263 * Emits the #GDBusAuthObserver::authorize-authenticated-peer signal on @observer.
264 *
265 * Returns: %TRUE if the peer is authorized, %FALSE if not.
266 *
267 * Since: 2.26
268 */
269 gboolean
270 g_dbus_auth_observer_authorize_authenticated_peer (GDBusAuthObserver *observer,
271 GIOStream *stream,
272 GCredentials *credentials)
273 {
274 gboolean denied;
275
276 denied = FALSE;
277 g_signal_emit (observer,
278 signals[AUTHORIZE_AUTHENTICATED_PEER_SIGNAL],
279 0,
280 stream,
281 credentials,
282 &denied);
283 return denied;
284 }
285
286 /**
287 * g_dbus_auth_observer_allow_mechanism:
288 * @observer: A #GDBusAuthObserver.
289 * @mechanism: The name of the mechanism, e.g. `DBUS_COOKIE_SHA1`.
290 *
291 * Emits the #GDBusAuthObserver::allow-mechanism signal on @observer.
292 *
293 * Returns: %TRUE if @mechanism can be used to authenticate the other peer, %FALSE if not.
294 *
295 * Since: 2.34
296 */
297 gboolean
298 g_dbus_auth_observer_allow_mechanism (GDBusAuthObserver *observer,
299 const gchar *mechanism)
300 {
301 gboolean ret;
302
303 ret = FALSE;
304 g_signal_emit (observer,
305 signals[ALLOW_MECHANISM_SIGNAL],
306 0,
307 mechanism,
308 &ret);
309 return ret;
310 }