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