/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 | } |