Coverage Report

Created: 2025-06-13 06:55

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