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