Coverage Report

Created: 2025-07-01 07:09

/src/glib/gio/gtlspassword.c
Line
Count
Source (jump to first uncovered line)
1
/* GIO - GLib Input, Output and Streaming Library
2
 *
3
 * Copyright (C) 2011 Collabora, Ltd.
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: Stef Walter <stefw@collabora.co.uk>
19
 */
20
21
#include "config.h"
22
#include "glib.h"
23
#include "glibintl.h"
24
25
#include "gioenumtypes.h"
26
#include "gtlspassword.h"
27
28
#include <string.h>
29
30
/**
31
 * SECTION:gtlspassword
32
 * @title: GTlsPassword
33
 * @short_description: TLS Passwords for prompting
34
 * @include: gio/gio.h
35
 *
36
 * Holds a password used in TLS.
37
 */
38
39
/**
40
 * GTlsPassword:
41
 *
42
 * An abstract interface representing a password used in TLS. Often used in
43
 * user interaction such as unlocking a key storage token.
44
 *
45
 * Since: 2.30
46
 */
47
48
enum
49
{
50
  PROP_0,
51
  PROP_FLAGS,
52
  PROP_DESCRIPTION,
53
  PROP_WARNING
54
};
55
56
struct _GTlsPasswordPrivate
57
{
58
  guchar *value;
59
  gsize length;
60
  GDestroyNotify destroy;
61
  GTlsPasswordFlags flags;
62
  gchar *description;
63
  gchar *warning;
64
};
65
66
G_DEFINE_TYPE_WITH_PRIVATE (GTlsPassword, g_tls_password, G_TYPE_OBJECT)
67
68
static void
69
g_tls_password_init (GTlsPassword *password)
70
0
{
71
0
  password->priv = g_tls_password_get_instance_private (password);
72
0
}
73
74
static const guchar *
75
g_tls_password_real_get_value (GTlsPassword  *password,
76
                               gsize         *length)
77
0
{
78
0
  if (length)
79
0
    *length = password->priv->length;
80
0
  return password->priv->value;
81
0
}
82
83
static void
84
g_tls_password_real_set_value (GTlsPassword   *password,
85
                               guchar         *value,
86
                               gssize          length,
87
                               GDestroyNotify  destroy)
88
0
{
89
0
  if (password->priv->destroy)
90
0
      (password->priv->destroy) (password->priv->value);
91
0
  password->priv->destroy = NULL;
92
0
  password->priv->value = NULL;
93
0
  password->priv->length = 0;
94
95
0
  if (length < 0)
96
0
    length = strlen ((gchar*) value);
97
98
0
  password->priv->value = value;
99
0
  password->priv->length = length;
100
0
  password->priv->destroy = destroy;
101
0
}
102
103
static const gchar*
104
g_tls_password_real_get_default_warning (GTlsPassword  *password)
105
0
{
106
0
  GTlsPasswordFlags flags;
107
108
0
  flags = g_tls_password_get_flags (password);
109
110
0
  if (flags & G_TLS_PASSWORD_FINAL_TRY)
111
0
    return _("This is the last chance to enter the password correctly before your access is locked out.");
112
0
  if (flags & G_TLS_PASSWORD_MANY_TRIES)
113
    /* Translators: This is not the 'This is the last chance' string. It is
114
     * displayed when more than one attempt is allowed. */
115
0
    return _("Several passwords entered have been incorrect, and your access will be locked out after further failures.");
116
0
  if (flags & G_TLS_PASSWORD_RETRY)
117
0
    return _("The password entered is incorrect.");
118
119
0
  return NULL;
120
0
}
121
122
static void
123
g_tls_password_get_property (GObject    *object,
124
                             guint       prop_id,
125
                             GValue     *value,
126
                             GParamSpec *pspec)
127
0
{
128
0
  GTlsPassword *password = G_TLS_PASSWORD (object);
129
130
0
  switch (prop_id)
131
0
    {
132
0
    case PROP_FLAGS:
133
0
      g_value_set_flags (value, g_tls_password_get_flags (password));
134
0
      break;
135
0
    case PROP_WARNING:
136
0
      g_value_set_string (value, g_tls_password_get_warning (password));
137
0
      break;
138
0
    case PROP_DESCRIPTION:
139
0
      g_value_set_string (value, g_tls_password_get_description (password));
140
0
      break;
141
0
    default:
142
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
143
0
      break;
144
0
    }
145
0
}
146
147
static void
148
g_tls_password_set_property (GObject      *object,
149
                             guint         prop_id,
150
                             const GValue *value,
151
                             GParamSpec   *pspec)
152
0
{
153
0
  GTlsPassword *password = G_TLS_PASSWORD (object);
154
155
0
  switch (prop_id)
156
0
    {
157
0
    case PROP_FLAGS:
158
0
      g_tls_password_set_flags (password, g_value_get_flags (value));
159
0
      break;
160
0
    case PROP_WARNING:
161
0
      g_tls_password_set_warning (password, g_value_get_string (value));
162
0
      break;
163
0
    case PROP_DESCRIPTION:
164
0
      g_tls_password_set_description (password, g_value_get_string (value));
165
0
      break;
166
0
    default:
167
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
168
0
      break;
169
0
    }
170
0
}
171
172
static void
173
g_tls_password_finalize (GObject *object)
174
0
{
175
0
  GTlsPassword *password = G_TLS_PASSWORD (object);
176
177
0
  g_tls_password_real_set_value (password, NULL, 0, NULL);
178
0
  g_free (password->priv->warning);
179
0
  g_free (password->priv->description);
180
181
0
  G_OBJECT_CLASS (g_tls_password_parent_class)->finalize (object);
182
0
}
183
184
static void
185
g_tls_password_class_init (GTlsPasswordClass *klass)
186
0
{
187
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
188
189
0
  klass->get_value = g_tls_password_real_get_value;
190
0
  klass->set_value = g_tls_password_real_set_value;
191
0
  klass->get_default_warning = g_tls_password_real_get_default_warning;
192
193
0
  gobject_class->get_property = g_tls_password_get_property;
194
0
  gobject_class->set_property = g_tls_password_set_property;
195
0
  gobject_class->finalize = g_tls_password_finalize;
196
197
0
  g_object_class_install_property (gobject_class, PROP_FLAGS,
198
0
           g_param_spec_flags ("flags",
199
0
                   P_("Flags"),
200
0
                   P_("Flags about the password"),
201
0
                   G_TYPE_TLS_PASSWORD_FLAGS,
202
0
                   G_TLS_PASSWORD_NONE,
203
0
                   G_PARAM_READWRITE |
204
0
                   G_PARAM_STATIC_STRINGS));
205
206
0
  g_object_class_install_property (gobject_class, PROP_DESCRIPTION,
207
0
           g_param_spec_string ("description",
208
0
              P_("Description"),
209
0
              P_("Description of what the password is for"),
210
0
              NULL,
211
0
              G_PARAM_READWRITE |
212
0
              G_PARAM_STATIC_STRINGS));
213
214
0
  g_object_class_install_property (gobject_class, PROP_WARNING,
215
0
           g_param_spec_string ("warning",
216
0
              P_("Warning"),
217
0
              P_("Warning about the password"),
218
0
              NULL,
219
0
              G_PARAM_READWRITE |
220
0
              G_PARAM_STATIC_STRINGS));
221
222
0
}
223
224
/**
225
 * g_tls_password_new:
226
 * @flags: the password flags
227
 * @description: description of what the password is for
228
 *
229
 * Create a new #GTlsPassword object.
230
 *
231
 * Returns: (transfer full): The newly allocated password object
232
 */
233
GTlsPassword *
234
g_tls_password_new (GTlsPasswordFlags  flags,
235
                    const gchar       *description)
236
0
{
237
0
  return g_object_new (G_TYPE_TLS_PASSWORD,
238
0
                       "flags", flags,
239
0
                       "description", description,
240
0
                       NULL);
241
0
}
242
243
/**
244
 * g_tls_password_get_value:
245
 * @password: a #GTlsPassword object
246
 * @length: (nullable): location to place the length of the password.
247
 *
248
 * Get the password value. If @length is not %NULL then it will be
249
 * filled in with the length of the password value. (Note that the
250
 * password value is not nul-terminated, so you can only pass %NULL
251
 * for @length in contexts where you know the password will have a
252
 * certain fixed length.)
253
 *
254
 * Returns: The password value (owned by the password object).
255
 *
256
 * Since: 2.30
257
 */
258
const guchar *
259
g_tls_password_get_value (GTlsPassword  *password,
260
                          gsize         *length)
261
0
{
262
0
  g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL);
263
0
  return G_TLS_PASSWORD_GET_CLASS (password)->get_value (password, length);
264
0
}
265
266
/**
267
 * g_tls_password_set_value:
268
 * @password: a #GTlsPassword object
269
 * @value: (array length=length): the new password value
270
 * @length: the length of the password, or -1
271
 *
272
 * Set the value for this password. The @value will be copied by the password
273
 * object.
274
 *
275
 * Specify the @length, for a non-nul-terminated password. Pass -1 as
276
 * @length if using a nul-terminated password, and @length will be
277
 * calculated automatically. (Note that the terminating nul is not
278
 * considered part of the password in this case.)
279
 *
280
 * Since: 2.30
281
 */
282
void
283
g_tls_password_set_value (GTlsPassword  *password,
284
                          const guchar  *value,
285
                          gssize         length)
286
0
{
287
0
  g_return_if_fail (G_IS_TLS_PASSWORD (password));
288
289
0
  if (length < 0)
290
0
    {
291
      /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */
292
0
      gsize length_unsigned = strlen ((gchar *) value);
293
0
      g_return_if_fail (length_unsigned <= G_MAXSSIZE);
294
0
      length = (gssize) length_unsigned;
295
0
    }
296
297
0
  g_tls_password_set_value_full (password, g_memdup2 (value, (gsize) length), length, g_free);
298
0
}
299
300
/**
301
 * g_tls_password_set_value_full:
302
 * @password: a #GTlsPassword object
303
 * @value: (array length=length): the value for the password
304
 * @length: the length of the password, or -1
305
 * @destroy: (nullable): a function to use to free the password.
306
 *
307
 * Provide the value for this password.
308
 *
309
 * The @value will be owned by the password object, and later freed using
310
 * the @destroy function callback.
311
 *
312
 * Specify the @length, for a non-nul-terminated password. Pass -1 as
313
 * @length if using a nul-terminated password, and @length will be
314
 * calculated automatically. (Note that the terminating nul is not
315
 * considered part of the password in this case.)
316
 *
317
 * Virtual: set_value
318
 * Since: 2.30
319
 */
320
void
321
g_tls_password_set_value_full (GTlsPassword   *password,
322
                               guchar         *value,
323
                               gssize          length,
324
                               GDestroyNotify  destroy)
325
0
{
326
0
  g_return_if_fail (G_IS_TLS_PASSWORD (password));
327
0
  G_TLS_PASSWORD_GET_CLASS (password)->set_value (password, value,
328
0
                                                  length, destroy);
329
0
}
330
331
/**
332
 * g_tls_password_get_flags:
333
 * @password: a #GTlsPassword object
334
 *
335
 * Get flags about the password.
336
 *
337
 * Returns: The flags about the password.
338
 *
339
 * Since: 2.30
340
 */
341
GTlsPasswordFlags
342
g_tls_password_get_flags (GTlsPassword *password)
343
0
{
344
0
  g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_PASSWORD_NONE);
345
0
  return password->priv->flags;
346
0
}
347
348
/**
349
 * g_tls_password_set_flags:
350
 * @password: a #GTlsPassword object
351
 * @flags: The flags about the password
352
 *
353
 * Set flags about the password.
354
 *
355
 * Since: 2.30
356
 */
357
void
358
g_tls_password_set_flags (GTlsPassword      *password,
359
                          GTlsPasswordFlags  flags)
360
0
{
361
0
  g_return_if_fail (G_IS_TLS_PASSWORD (password));
362
363
0
  password->priv->flags = flags;
364
365
0
  g_object_notify (G_OBJECT (password), "flags");
366
0
}
367
368
/**
369
 * g_tls_password_get_description:
370
 * @password: a #GTlsPassword object
371
 *
372
 * Get a description string about what the password will be used for.
373
 *
374
 * Returns: The description of the password.
375
 *
376
 * Since: 2.30
377
 */
378
const gchar*
379
g_tls_password_get_description (GTlsPassword *password)
380
0
{
381
0
  g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL);
382
0
  return password->priv->description;
383
0
}
384
385
/**
386
 * g_tls_password_set_description:
387
 * @password: a #GTlsPassword object
388
 * @description: The description of the password
389
 *
390
 * Set a description string about what the password will be used for.
391
 *
392
 * Since: 2.30
393
 */
394
void
395
g_tls_password_set_description (GTlsPassword      *password,
396
                                const gchar       *description)
397
0
{
398
0
  gchar *copy;
399
400
0
  g_return_if_fail (G_IS_TLS_PASSWORD (password));
401
402
0
  copy = g_strdup (description);
403
0
  g_free (password->priv->description);
404
0
  password->priv->description = copy;
405
406
0
  g_object_notify (G_OBJECT (password), "description");
407
0
}
408
409
/**
410
 * g_tls_password_get_warning:
411
 * @password: a #GTlsPassword object
412
 *
413
 * Get a user readable translated warning. Usually this warning is a
414
 * representation of the password flags returned from
415
 * g_tls_password_get_flags().
416
 *
417
 * Returns: The warning.
418
 *
419
 * Since: 2.30
420
 */
421
const gchar *
422
g_tls_password_get_warning (GTlsPassword      *password)
423
0
{
424
0
  g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL);
425
426
0
  if (password->priv->warning == NULL)
427
0
    return G_TLS_PASSWORD_GET_CLASS (password)->get_default_warning (password);
428
429
0
  return password->priv->warning;
430
0
}
431
432
/**
433
 * g_tls_password_set_warning:
434
 * @password: a #GTlsPassword object
435
 * @warning: The user readable warning
436
 *
437
 * Set a user readable translated warning. Usually this warning is a
438
 * representation of the password flags returned from
439
 * g_tls_password_get_flags().
440
 *
441
 * Since: 2.30
442
 */
443
void
444
g_tls_password_set_warning (GTlsPassword      *password,
445
                            const gchar       *warning)
446
0
{
447
0
  gchar *copy;
448
449
0
  g_return_if_fail (G_IS_TLS_PASSWORD (password));
450
451
0
  copy = g_strdup (warning);
452
0
  g_free (password->priv->warning);
453
0
  password->priv->warning = copy;
454
455
0
  g_object_notify (G_OBJECT (password), "warning");
456
0
}