Coverage Report

Created: 2025-07-01 07:09

/src/glib/gio/gdbusauthmechanismexternal.c
Line
Count
Source (jump to first uncovered line)
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 <string.h>
24
25
#include "gdbusauthmechanismexternal.h"
26
#include "gcredentials.h"
27
#include "gdbuserror.h"
28
#include "gioenumtypes.h"
29
30
#include "glibintl.h"
31
32
struct _GDBusAuthMechanismExternalPrivate
33
{
34
  gboolean is_client;
35
  gboolean is_server;
36
  GDBusAuthMechanismState state;
37
};
38
39
static gint                     mechanism_get_priority              (void);
40
static const gchar             *mechanism_get_name                  (void);
41
42
static gboolean                 mechanism_is_supported              (GDBusAuthMechanism   *mechanism);
43
static gchar                   *mechanism_encode_data               (GDBusAuthMechanism   *mechanism,
44
                                                                     const gchar          *data,
45
                                                                     gsize                 data_len,
46
                                                                     gsize                *out_data_len);
47
static gchar                   *mechanism_decode_data               (GDBusAuthMechanism   *mechanism,
48
                                                                     const gchar          *data,
49
                                                                     gsize                 data_len,
50
                                                                     gsize                *out_data_len);
51
static GDBusAuthMechanismState  mechanism_server_get_state          (GDBusAuthMechanism   *mechanism);
52
static void                     mechanism_server_initiate           (GDBusAuthMechanism   *mechanism,
53
                                                                     const gchar          *initial_response,
54
                                                                     gsize                 initial_response_len);
55
static void                     mechanism_server_data_receive       (GDBusAuthMechanism   *mechanism,
56
                                                                     const gchar          *data,
57
                                                                     gsize                 data_len);
58
static gchar                   *mechanism_server_data_send          (GDBusAuthMechanism   *mechanism,
59
                                                                     gsize                *out_data_len);
60
static gchar                   *mechanism_server_get_reject_reason  (GDBusAuthMechanism   *mechanism);
61
static void                     mechanism_server_shutdown           (GDBusAuthMechanism   *mechanism);
62
static GDBusAuthMechanismState  mechanism_client_get_state          (GDBusAuthMechanism   *mechanism);
63
static gchar                   *mechanism_client_initiate           (GDBusAuthMechanism   *mechanism,
64
                                                                     gsize                *out_initial_response_len);
65
static void                     mechanism_client_data_receive       (GDBusAuthMechanism   *mechanism,
66
                                                                     const gchar          *data,
67
                                                                     gsize                 data_len);
68
static gchar                   *mechanism_client_data_send          (GDBusAuthMechanism   *mechanism,
69
                                                                     gsize                *out_data_len);
70
static void                     mechanism_client_shutdown           (GDBusAuthMechanism   *mechanism);
71
72
/* ---------------------------------------------------------------------------------------------------- */
73
74
G_DEFINE_TYPE_WITH_PRIVATE (GDBusAuthMechanismExternal, _g_dbus_auth_mechanism_external, G_TYPE_DBUS_AUTH_MECHANISM)
75
76
/* ---------------------------------------------------------------------------------------------------- */
77
78
static void
79
_g_dbus_auth_mechanism_external_finalize (GObject *object)
80
0
{
81
  //GDBusAuthMechanismExternal *mechanism = G_DBUS_AUTH_MECHANISM_EXTERNAL (object);
82
83
0
  if (G_OBJECT_CLASS (_g_dbus_auth_mechanism_external_parent_class)->finalize != NULL)
84
0
    G_OBJECT_CLASS (_g_dbus_auth_mechanism_external_parent_class)->finalize (object);
85
0
}
86
87
static void
88
_g_dbus_auth_mechanism_external_class_init (GDBusAuthMechanismExternalClass *klass)
89
0
{
90
0
  GObjectClass *gobject_class;
91
0
  GDBusAuthMechanismClass *mechanism_class;
92
93
0
  gobject_class = G_OBJECT_CLASS (klass);
94
0
  gobject_class->finalize = _g_dbus_auth_mechanism_external_finalize;
95
96
0
  mechanism_class = G_DBUS_AUTH_MECHANISM_CLASS (klass);
97
0
  mechanism_class->get_name                  = mechanism_get_name;
98
0
  mechanism_class->get_priority              = mechanism_get_priority;
99
0
  mechanism_class->is_supported              = mechanism_is_supported;
100
0
  mechanism_class->encode_data               = mechanism_encode_data;
101
0
  mechanism_class->decode_data               = mechanism_decode_data;
102
0
  mechanism_class->server_get_state          = mechanism_server_get_state;
103
0
  mechanism_class->server_initiate           = mechanism_server_initiate;
104
0
  mechanism_class->server_data_receive       = mechanism_server_data_receive;
105
0
  mechanism_class->server_data_send          = mechanism_server_data_send;
106
0
  mechanism_class->server_get_reject_reason  = mechanism_server_get_reject_reason;
107
0
  mechanism_class->server_shutdown           = mechanism_server_shutdown;
108
0
  mechanism_class->client_get_state          = mechanism_client_get_state;
109
0
  mechanism_class->client_initiate           = mechanism_client_initiate;
110
0
  mechanism_class->client_data_receive       = mechanism_client_data_receive;
111
0
  mechanism_class->client_data_send          = mechanism_client_data_send;
112
0
  mechanism_class->client_shutdown           = mechanism_client_shutdown;
113
0
}
114
115
static void
116
_g_dbus_auth_mechanism_external_init (GDBusAuthMechanismExternal *mechanism)
117
0
{
118
0
  mechanism->priv = _g_dbus_auth_mechanism_external_get_instance_private (mechanism);
119
0
}
120
121
/* ---------------------------------------------------------------------------------------------------- */
122
123
static gboolean
124
mechanism_is_supported (GDBusAuthMechanism *mechanism)
125
0
{
126
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), FALSE);
127
  /* This mechanism is only available if credentials has been exchanged */
128
0
  if (_g_dbus_auth_mechanism_get_credentials (mechanism) != NULL)
129
0
    return TRUE;
130
0
  else
131
0
    return FALSE;
132
0
}
133
134
static gint
135
mechanism_get_priority (void)
136
0
{
137
  /* We prefer EXTERNAL to most other mechanism (DBUS_COOKIE_SHA1 and ANONYMOUS) */
138
0
  return 100;
139
0
}
140
141
static const gchar *
142
mechanism_get_name (void)
143
0
{
144
0
  return "EXTERNAL";
145
0
}
146
147
static gchar *
148
mechanism_encode_data (GDBusAuthMechanism   *mechanism,
149
                       const gchar          *data,
150
                       gsize                 data_len,
151
                       gsize                *out_data_len)
152
0
{
153
0
  return NULL;
154
0
}
155
156
157
static gchar *
158
mechanism_decode_data (GDBusAuthMechanism   *mechanism,
159
                       const gchar          *data,
160
                       gsize                 data_len,
161
                       gsize                *out_data_len)
162
0
{
163
0
  return NULL;
164
0
}
165
166
/* ---------------------------------------------------------------------------------------------------- */
167
168
static GDBusAuthMechanismState
169
mechanism_server_get_state (GDBusAuthMechanism   *mechanism)
170
0
{
171
0
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
172
173
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
174
0
  g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
175
176
0
  return m->priv->state;
177
0
}
178
179
static gboolean
180
data_matches_credentials (const gchar  *data,
181
                          gsize         data_len,
182
                          GCredentials *credentials)
183
0
{
184
0
  gboolean match;
185
186
0
  match = FALSE;
187
188
0
  if (credentials == NULL)
189
0
    goto out;
190
191
0
  if (data == NULL || data_len == 0)
192
0
    goto out;
193
194
0
#if defined(G_OS_UNIX)
195
0
  {
196
0
    gint64 alleged_uid;
197
0
    gchar *endp;
198
199
    /* on UNIX, this is the uid as a string in base 10 */
200
0
    alleged_uid = g_ascii_strtoll (data, &endp, 10);
201
0
    if (*endp == '\0')
202
0
      {
203
0
        if (g_credentials_get_unix_user (credentials, NULL) == alleged_uid)
204
0
          {
205
0
            match = TRUE;
206
0
          }
207
0
      }
208
0
  }
209
#else
210
  /* TODO: Dont know how to compare credentials on this OS. Please implement. */
211
#endif
212
213
0
 out:
214
0
  return match;
215
0
}
216
217
static void
218
mechanism_server_initiate (GDBusAuthMechanism   *mechanism,
219
                           const gchar          *initial_response,
220
                           gsize                 initial_response_len)
221
0
{
222
0
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
223
224
0
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
225
0
  g_return_if_fail (!m->priv->is_server && !m->priv->is_client);
226
227
0
  m->priv->is_server = TRUE;
228
229
0
  if (initial_response != NULL)
230
0
    {
231
0
      if (data_matches_credentials (initial_response,
232
0
                                    initial_response_len,
233
0
                                    _g_dbus_auth_mechanism_get_credentials (mechanism)))
234
0
        {
235
0
          m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
236
0
        }
237
0
      else
238
0
        {
239
0
          m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
240
0
        }
241
0
    }
242
0
  else
243
0
    {
244
0
      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
245
0
    }
246
0
}
247
248
static void
249
mechanism_server_data_receive (GDBusAuthMechanism   *mechanism,
250
                               const gchar          *data,
251
                               gsize                 data_len)
252
0
{
253
0
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
254
255
0
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
256
0
  g_return_if_fail (m->priv->is_server && !m->priv->is_client);
257
0
  g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
258
259
0
  if (data_matches_credentials (data,
260
0
                                data_len,
261
0
                                _g_dbus_auth_mechanism_get_credentials (mechanism)))
262
0
    {
263
0
      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
264
0
    }
265
0
  else
266
0
    {
267
0
      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
268
0
    }
269
0
}
270
271
static gchar *
272
mechanism_server_data_send (GDBusAuthMechanism   *mechanism,
273
                            gsize                *out_data_len)
274
0
{
275
0
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
276
277
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
278
0
  g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
279
0
  g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
280
281
  /* can never end up here because we are never in the HAVE_DATA_TO_SEND state */
282
0
  g_assert_not_reached ();
283
284
0
  return NULL;
285
0
}
286
287
static gchar *
288
mechanism_server_get_reject_reason (GDBusAuthMechanism   *mechanism)
289
0
{
290
0
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
291
292
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
293
0
  g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
294
0
  g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
295
296
  /* can never end up here because we are never in the REJECTED state */
297
0
  g_assert_not_reached ();
298
299
0
  return NULL;
300
0
}
301
302
static void
303
mechanism_server_shutdown (GDBusAuthMechanism   *mechanism)
304
0
{
305
0
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
306
307
0
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
308
0
  g_return_if_fail (m->priv->is_server && !m->priv->is_client);
309
310
0
  m->priv->is_server = FALSE;
311
0
}
312
313
/* ---------------------------------------------------------------------------------------------------- */
314
315
static GDBusAuthMechanismState
316
mechanism_client_get_state (GDBusAuthMechanism   *mechanism)
317
0
{
318
0
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
319
320
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
321
0
  g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
322
323
0
  return m->priv->state;
324
0
}
325
326
static gchar *
327
mechanism_client_initiate (GDBusAuthMechanism   *mechanism,
328
                           gsize                *out_initial_response_len)
329
0
{
330
0
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
331
0
  gchar *initial_response = NULL;
332
0
  GCredentials *credentials;
333
334
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
335
0
  g_return_val_if_fail (!m->priv->is_server && !m->priv->is_client, NULL);
336
337
0
  m->priv->is_client = TRUE;
338
0
  m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
339
340
0
  *out_initial_response_len = 0;
341
342
0
  credentials = _g_dbus_auth_mechanism_get_credentials (mechanism);
343
0
  g_assert (credentials != NULL);
344
345
  /* return the uid */
346
0
#if defined(G_OS_UNIX)
347
0
  initial_response = g_strdup_printf ("%" G_GINT64_FORMAT, (gint64) g_credentials_get_unix_user (credentials, NULL));
348
0
 *out_initial_response_len = strlen (initial_response);
349
#elif defined(G_OS_WIN32)
350
#ifdef __GNUC__
351
#pragma GCC diagnostic push
352
#pragma GCC diagnostic warning "-Wcpp"
353
#warning Dont know how to send credentials on this OS. The EXTERNAL D-Bus authentication mechanism will not work.
354
#pragma GCC diagnostic pop
355
#endif
356
  m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
357
#endif
358
0
  return initial_response;
359
0
}
360
361
static void
362
mechanism_client_data_receive (GDBusAuthMechanism   *mechanism,
363
                               const gchar          *data,
364
                               gsize                 data_len)
365
0
{
366
0
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
367
368
0
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
369
0
  g_return_if_fail (m->priv->is_client && !m->priv->is_server);
370
0
  g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
371
372
  /* can never end up here because we are never in the WAITING_FOR_DATA state */
373
0
  g_assert_not_reached ();
374
0
}
375
376
static gchar *
377
mechanism_client_data_send (GDBusAuthMechanism   *mechanism,
378
                            gsize                *out_data_len)
379
0
{
380
0
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
381
382
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
383
0
  g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, NULL);
384
0
  g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
385
386
  /* can never end up here because we are never in the HAVE_DATA_TO_SEND state */
387
0
  g_assert_not_reached ();
388
389
0
  return NULL;
390
0
}
391
392
static void
393
mechanism_client_shutdown (GDBusAuthMechanism   *mechanism)
394
0
{
395
0
  GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
396
397
0
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
398
0
  g_return_if_fail (m->priv->is_client && !m->priv->is_server);
399
400
0
  m->priv->is_client = FALSE;
401
0
}
402
403
/* ---------------------------------------------------------------------------------------------------- */