Imported Upstream version 2.67.4
[platform/upstream/glib.git] / gio / gtlspassword.c
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 {
71   password->priv = g_tls_password_get_instance_private (password);
72 }
73
74 static const guchar *
75 g_tls_password_real_get_value (GTlsPassword  *password,
76                                gsize         *length)
77 {
78   if (length)
79     *length = password->priv->length;
80   return password->priv->value;
81 }
82
83 static void
84 g_tls_password_real_set_value (GTlsPassword   *password,
85                                guchar         *value,
86                                gssize          length,
87                                GDestroyNotify  destroy)
88 {
89   if (password->priv->destroy)
90       (password->priv->destroy) (password->priv->value);
91   password->priv->destroy = NULL;
92   password->priv->value = NULL;
93   password->priv->length = 0;
94
95   if (length < 0)
96     length = strlen ((gchar*) value);
97
98   password->priv->value = value;
99   password->priv->length = length;
100   password->priv->destroy = destroy;
101 }
102
103 static const gchar*
104 g_tls_password_real_get_default_warning (GTlsPassword  *password)
105 {
106   GTlsPasswordFlags flags;
107
108   flags = g_tls_password_get_flags (password);
109
110   if (flags & G_TLS_PASSWORD_FINAL_TRY)
111     return _("This is the last chance to enter the password correctly before your access is locked out.");
112   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     return _("Several passwords entered have been incorrect, and your access will be locked out after further failures.");
116   if (flags & G_TLS_PASSWORD_RETRY)
117     return _("The password entered is incorrect.");
118
119   return NULL;
120 }
121
122 static void
123 g_tls_password_get_property (GObject    *object,
124                              guint       prop_id,
125                              GValue     *value,
126                              GParamSpec *pspec)
127 {
128   GTlsPassword *password = G_TLS_PASSWORD (object);
129
130   switch (prop_id)
131     {
132     case PROP_FLAGS:
133       g_value_set_flags (value, g_tls_password_get_flags (password));
134       break;
135     case PROP_WARNING:
136       g_value_set_string (value, g_tls_password_get_warning (password));
137       break;
138     case PROP_DESCRIPTION:
139       g_value_set_string (value, g_tls_password_get_description (password));
140       break;
141     default:
142       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
143       break;
144     }
145 }
146
147 static void
148 g_tls_password_set_property (GObject      *object,
149                              guint         prop_id,
150                              const GValue *value,
151                              GParamSpec   *pspec)
152 {
153   GTlsPassword *password = G_TLS_PASSWORD (object);
154
155   switch (prop_id)
156     {
157     case PROP_FLAGS:
158       g_tls_password_set_flags (password, g_value_get_flags (value));
159       break;
160     case PROP_WARNING:
161       g_tls_password_set_warning (password, g_value_get_string (value));
162       break;
163     case PROP_DESCRIPTION:
164       g_tls_password_set_description (password, g_value_get_string (value));
165       break;
166     default:
167       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
168       break;
169     }
170 }
171
172 static void
173 g_tls_password_finalize (GObject *object)
174 {
175   GTlsPassword *password = G_TLS_PASSWORD (object);
176
177   g_tls_password_real_set_value (password, NULL, 0, NULL);
178   g_free (password->priv->warning);
179   g_free (password->priv->description);
180
181   G_OBJECT_CLASS (g_tls_password_parent_class)->finalize (object);
182 }
183
184 static void
185 g_tls_password_class_init (GTlsPasswordClass *klass)
186 {
187   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
188
189   klass->get_value = g_tls_password_real_get_value;
190   klass->set_value = g_tls_password_real_set_value;
191   klass->get_default_warning = g_tls_password_real_get_default_warning;
192
193   gobject_class->get_property = g_tls_password_get_property;
194   gobject_class->set_property = g_tls_password_set_property;
195   gobject_class->finalize = g_tls_password_finalize;
196
197   g_object_class_install_property (gobject_class, PROP_FLAGS,
198                                    g_param_spec_flags ("flags",
199                                                        P_("Flags"),
200                                                        P_("Flags about the password"),
201                                                        G_TYPE_TLS_PASSWORD_FLAGS,
202                                                        G_TLS_PASSWORD_NONE,
203                                                        G_PARAM_READWRITE |
204                                                        G_PARAM_STATIC_STRINGS));
205
206   g_object_class_install_property (gobject_class, PROP_DESCRIPTION,
207                                    g_param_spec_string ("description",
208                                                         P_("Description"),
209                                                         P_("Description of what the password is for"),
210                                                         NULL,
211                                                         G_PARAM_READWRITE |
212                                                         G_PARAM_STATIC_STRINGS));
213
214   g_object_class_install_property (gobject_class, PROP_WARNING,
215                                    g_param_spec_string ("warning",
216                                                         P_("Warning"),
217                                                         P_("Warning about the password"),
218                                                         NULL,
219                                                         G_PARAM_READWRITE |
220                                                         G_PARAM_STATIC_STRINGS));
221
222 }
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 {
237   return g_object_new (G_TYPE_TLS_PASSWORD,
238                        "flags", flags,
239                        "description", description,
240                        NULL);
241 }
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 {
262   g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL);
263   return G_TLS_PASSWORD_GET_CLASS (password)->get_value (password, length);
264 }
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 {
287   g_return_if_fail (G_IS_TLS_PASSWORD (password));
288
289   if (length < 0)
290     {
291       /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */
292       gsize length_unsigned = strlen ((gchar *) value);
293       g_return_if_fail (length_unsigned <= G_MAXSSIZE);
294       length = (gssize) length_unsigned;
295     }
296
297   g_tls_password_set_value_full (password, g_memdup2 (value, (gsize) length), length, g_free);
298 }
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 {
326   g_return_if_fail (G_IS_TLS_PASSWORD (password));
327   G_TLS_PASSWORD_GET_CLASS (password)->set_value (password, value,
328                                                   length, destroy);
329 }
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 {
344   g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_PASSWORD_NONE);
345   return password->priv->flags;
346 }
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 {
361   g_return_if_fail (G_IS_TLS_PASSWORD (password));
362
363   password->priv->flags = flags;
364
365   g_object_notify (G_OBJECT (password), "flags");
366 }
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 {
381   g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL);
382   return password->priv->description;
383 }
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 {
398   gchar *copy;
399
400   g_return_if_fail (G_IS_TLS_PASSWORD (password));
401
402   copy = g_strdup (description);
403   g_free (password->priv->description);
404   password->priv->description = copy;
405
406   g_object_notify (G_OBJECT (password), "description");
407 }
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 {
424   g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL);
425
426   if (password->priv->warning == NULL)
427     return G_TLS_PASSWORD_GET_CLASS (password)->get_default_warning (password);
428
429   return password->priv->warning;
430 }
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 {
447   gchar *copy;
448
449   g_return_if_fail (G_IS_TLS_PASSWORD (password));
450
451   copy = g_strdup (warning);
452   g_free (password->priv->warning);
453   password->priv->warning = copy;
454
455   g_object_notify (G_OBJECT (password), "warning");
456 }