Coverage Report

Created: 2025-07-23 08:13

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