Branch data Line data Source code
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 : 424 : G_DEFINE_TYPE_WITH_PRIVATE (GTlsPassword, g_tls_password, G_TYPE_OBJECT)
60 : :
61 : : static void
62 : 43 : g_tls_password_init (GTlsPassword *password)
63 : : {
64 : 43 : password->priv = g_tls_password_get_instance_private (password);
65 : 43 : }
66 : :
67 : : static const guchar *
68 : 24 : g_tls_password_real_get_value (GTlsPassword *password,
69 : : gsize *length)
70 : : {
71 : 24 : if (length)
72 : 16 : *length = password->priv->length;
73 : 24 : return password->priv->value;
74 : : }
75 : :
76 : : static void
77 : 67 : g_tls_password_real_set_value (GTlsPassword *password,
78 : : guchar *value,
79 : : gssize length,
80 : : GDestroyNotify destroy)
81 : : {
82 : 67 : if (password->priv->destroy)
83 : 24 : (password->priv->destroy) (password->priv->value);
84 : 67 : password->priv->destroy = NULL;
85 : 67 : password->priv->value = NULL;
86 : 67 : password->priv->length = 0;
87 : :
88 : 67 : if (length < 0)
89 : 4 : length = strlen ((gchar*) value);
90 : :
91 : 67 : password->priv->value = value;
92 : 67 : password->priv->length = length;
93 : 67 : password->priv->destroy = destroy;
94 : 67 : }
95 : :
96 : : static const gchar*
97 : 1 : g_tls_password_real_get_default_warning (GTlsPassword *password)
98 : : {
99 : : GTlsPasswordFlags flags;
100 : :
101 : 1 : flags = g_tls_password_get_flags (password);
102 : :
103 : 1 : 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 : 1 : 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 : 1 : if (flags & G_TLS_PASSWORD_RETRY)
110 : 0 : return _("The password entered is incorrect.");
111 : :
112 : 1 : return NULL;
113 : : }
114 : :
115 : : static void
116 : 3 : g_tls_password_get_property (GObject *object,
117 : : guint prop_id,
118 : : GValue *value,
119 : : GParamSpec *pspec)
120 : : {
121 : 3 : GTlsPassword *password = G_TLS_PASSWORD (object);
122 : :
123 : 3 : switch (prop_id)
124 : : {
125 : 1 : case PROP_FLAGS:
126 : 1 : g_value_set_flags (value, g_tls_password_get_flags (password));
127 : 1 : break;
128 : 1 : case PROP_WARNING:
129 : 1 : g_value_set_string (value, g_tls_password_get_warning (password));
130 : 1 : break;
131 : 1 : case PROP_DESCRIPTION:
132 : 1 : g_value_set_string (value, g_tls_password_get_description (password));
133 : 1 : break;
134 : 0 : default:
135 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
136 : 0 : break;
137 : : }
138 : 3 : }
139 : :
140 : : static void
141 : 84 : g_tls_password_set_property (GObject *object,
142 : : guint prop_id,
143 : : const GValue *value,
144 : : GParamSpec *pspec)
145 : : {
146 : 84 : GTlsPassword *password = G_TLS_PASSWORD (object);
147 : :
148 : 84 : switch (prop_id)
149 : : {
150 : 42 : case PROP_FLAGS:
151 : 42 : g_tls_password_set_flags (password, g_value_get_flags (value));
152 : 42 : break;
153 : 0 : case PROP_WARNING:
154 : 0 : g_tls_password_set_warning (password, g_value_get_string (value));
155 : 0 : break;
156 : 42 : case PROP_DESCRIPTION:
157 : 42 : g_tls_password_set_description (password, g_value_get_string (value));
158 : 42 : break;
159 : 0 : default:
160 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
161 : 0 : break;
162 : : }
163 : 84 : }
164 : :
165 : : static void
166 : 43 : g_tls_password_finalize (GObject *object)
167 : : {
168 : 43 : GTlsPassword *password = G_TLS_PASSWORD (object);
169 : :
170 : 43 : g_tls_password_real_set_value (password, NULL, 0, NULL);
171 : 43 : g_free (password->priv->warning);
172 : 43 : g_free (password->priv->description);
173 : :
174 : 43 : G_OBJECT_CLASS (g_tls_password_parent_class)->finalize (object);
175 : 43 : }
176 : :
177 : : static void
178 : 3 : g_tls_password_class_init (GTlsPasswordClass *klass)
179 : : {
180 : 3 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
181 : :
182 : 3 : klass->get_value = g_tls_password_real_get_value;
183 : 3 : klass->set_value = g_tls_password_real_set_value;
184 : 3 : klass->get_default_warning = g_tls_password_real_get_default_warning;
185 : :
186 : 3 : gobject_class->get_property = g_tls_password_get_property;
187 : 3 : gobject_class->set_property = g_tls_password_set_property;
188 : 3 : 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 : 3 : g_object_class_install_property (gobject_class, PROP_FLAGS,
198 : : g_param_spec_flags ("flags", NULL, NULL,
199 : : G_TYPE_TLS_PASSWORD_FLAGS,
200 : : G_TLS_PASSWORD_NONE,
201 : : G_PARAM_READWRITE |
202 : : 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 : 3 : g_object_class_install_property (gobject_class, PROP_DESCRIPTION,
212 : : g_param_spec_string ("description", NULL, NULL,
213 : : NULL,
214 : : G_PARAM_READWRITE |
215 : : G_PARAM_STATIC_STRINGS));
216 : :
217 : : /**
218 : : * GTlsPassword:warning:
219 : : *
220 : : * Warning about the password.
221 : : *
222 : : * Since: 2.30
223 : : */
224 : 3 : g_object_class_install_property (gobject_class, PROP_WARNING,
225 : : g_param_spec_string ("warning", NULL, NULL,
226 : : NULL,
227 : : G_PARAM_READWRITE |
228 : : G_PARAM_STATIC_STRINGS));
229 : :
230 : 3 : }
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 : 42 : g_tls_password_new (GTlsPasswordFlags flags,
243 : : const gchar *description)
244 : : {
245 : 42 : return g_object_new (G_TYPE_TLS_PASSWORD,
246 : : "flags", flags,
247 : : "description", description,
248 : : NULL);
249 : : }
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 : 24 : g_tls_password_get_value (GTlsPassword *password,
268 : : gsize *length)
269 : : {
270 : 24 : g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL);
271 : 24 : return G_TLS_PASSWORD_GET_CLASS (password)->get_value (password, length);
272 : : }
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 : 16 : g_tls_password_set_value (GTlsPassword *password,
292 : : const guchar *value,
293 : : gssize length)
294 : : {
295 : 16 : g_return_if_fail (G_IS_TLS_PASSWORD (password));
296 : :
297 : 16 : if (length < 0)
298 : : {
299 : : /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */
300 : 4 : gsize length_unsigned = strlen ((gchar *) value);
301 : 4 : g_return_if_fail (length_unsigned <= G_MAXSSIZE);
302 : 4 : length = (gssize) length_unsigned;
303 : : }
304 : :
305 : 16 : g_tls_password_set_value_full (password, g_memdup2 (value, (gsize) length), length, g_free);
306 : : }
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 : 24 : g_tls_password_set_value_full (GTlsPassword *password,
329 : : guchar *value,
330 : : gssize length,
331 : : GDestroyNotify destroy)
332 : : {
333 : 24 : g_return_if_fail (G_IS_TLS_PASSWORD (password));
334 : 24 : G_TLS_PASSWORD_GET_CLASS (password)->set_value (password, value,
335 : : length, destroy);
336 : : }
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 : 2 : g_tls_password_get_flags (GTlsPassword *password)
350 : : {
351 : 2 : g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_PASSWORD_NONE);
352 : 2 : return password->priv->flags;
353 : : }
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 : 42 : g_tls_password_set_flags (GTlsPassword *password,
366 : : GTlsPasswordFlags flags)
367 : : {
368 : 42 : g_return_if_fail (G_IS_TLS_PASSWORD (password));
369 : :
370 : 42 : password->priv->flags = flags;
371 : :
372 : 42 : g_object_notify (G_OBJECT (password), "flags");
373 : : }
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 : 1 : g_tls_password_get_description (GTlsPassword *password)
387 : : {
388 : 1 : g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL);
389 : 1 : return password->priv->description;
390 : : }
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 : 42 : g_tls_password_set_description (GTlsPassword *password,
403 : : const gchar *description)
404 : : {
405 : : gchar *copy;
406 : :
407 : 42 : g_return_if_fail (G_IS_TLS_PASSWORD (password));
408 : :
409 : 42 : copy = g_strdup (description);
410 : 42 : g_free (password->priv->description);
411 : 42 : password->priv->description = copy;
412 : :
413 : 42 : g_object_notify (G_OBJECT (password), "description");
414 : : }
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 : 1 : g_tls_password_get_warning (GTlsPassword *password)
430 : : {
431 : 1 : g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL);
432 : :
433 : 1 : if (password->priv->warning == NULL)
434 : 1 : return G_TLS_PASSWORD_GET_CLASS (password)->get_default_warning (password);
435 : :
436 : 0 : return password->priv->warning;
437 : : }
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 : 0 : g_tls_password_set_warning (GTlsPassword *password,
452 : : const gchar *warning)
453 : : {
454 : : 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 : : }
|