| /* GIO - GLib Input, Output and Streaming Library |
| * |
| * Copyright (C) 2011 Collabora, Ltd. |
| * |
| * SPDX-License-Identifier: LGPL-2.1-or-later |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General |
| * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. |
| * |
| * Author: Stef Walter <stefw@collabora.co.uk> |
| */ |
| |
| #include "config.h" |
| #include "glib.h" |
| #include "glibintl.h" |
| |
| #include "gioenumtypes.h" |
| #include "gtlspassword.h" |
| |
| #include <string.h> |
| |
| /** |
| * GTlsPassword: |
| * |
| * An abstract interface representing a password used in TLS. Often used in |
| * user interaction such as unlocking a key storage token. |
| * |
| * Since: 2.30 |
| */ |
| |
| enum |
| { |
| PROP_0, |
| PROP_FLAGS, |
| PROP_DESCRIPTION, |
| PROP_WARNING |
| }; |
| |
| struct _GTlsPasswordPrivate |
| { |
| guchar *value; |
| gsize length; |
| GDestroyNotify destroy; |
| GTlsPasswordFlags flags; |
| gchar *description; |
| gchar *warning; |
| }; |
| |
| G_DEFINE_TYPE_WITH_PRIVATE (GTlsPassword, g_tls_password, G_TYPE_OBJECT) |
| |
| static void |
| g_tls_password_init (GTlsPassword *password) |
| { |
| password->priv = g_tls_password_get_instance_private (password); |
| } |
| |
| static const guchar * |
| g_tls_password_real_get_value (GTlsPassword *password, |
| gsize *length) |
| { |
| if (length) |
| *length = password->priv->length; |
| return password->priv->value; |
| } |
| |
| static void |
| g_tls_password_real_set_value (GTlsPassword *password, |
| guchar *value, |
| gssize length, |
| GDestroyNotify destroy) |
| { |
| if (password->priv->destroy) |
| (password->priv->destroy) (password->priv->value); |
| password->priv->destroy = NULL; |
| password->priv->value = NULL; |
| password->priv->length = 0; |
| |
| if (length < 0) |
| length = strlen ((gchar*) value); |
| |
| password->priv->value = value; |
| password->priv->length = length; |
| password->priv->destroy = destroy; |
| } |
| |
| static const gchar* |
| g_tls_password_real_get_default_warning (GTlsPassword *password) |
| { |
| GTlsPasswordFlags flags; |
| |
| flags = g_tls_password_get_flags (password); |
| |
| if (flags & G_TLS_PASSWORD_FINAL_TRY) |
| return _("This is the last chance to enter the password correctly before your access is locked out."); |
| if (flags & G_TLS_PASSWORD_MANY_TRIES) |
| /* Translators: This is not the 'This is the last chance' string. It is |
| * displayed when more than one attempt is allowed. */ |
| return _("Several passwords entered have been incorrect, and your access will be locked out after further failures."); |
| if (flags & G_TLS_PASSWORD_RETRY) |
| return _("The password entered is incorrect."); |
| |
| return NULL; |
| } |
| |
| static void |
| g_tls_password_get_property (GObject *object, |
| guint prop_id, |
| GValue *value, |
| GParamSpec *pspec) |
| { |
| GTlsPassword *password = G_TLS_PASSWORD (object); |
| |
| switch (prop_id) |
| { |
| case PROP_FLAGS: |
| g_value_set_flags (value, g_tls_password_get_flags (password)); |
| break; |
| case PROP_WARNING: |
| g_value_set_string (value, g_tls_password_get_warning (password)); |
| break; |
| case PROP_DESCRIPTION: |
| g_value_set_string (value, g_tls_password_get_description (password)); |
| break; |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
| break; |
| } |
| } |
| |
| static void |
| g_tls_password_set_property (GObject *object, |
| guint prop_id, |
| const GValue *value, |
| GParamSpec *pspec) |
| { |
| GTlsPassword *password = G_TLS_PASSWORD (object); |
| |
| switch (prop_id) |
| { |
| case PROP_FLAGS: |
| g_tls_password_set_flags (password, g_value_get_flags (value)); |
| break; |
| case PROP_WARNING: |
| g_tls_password_set_warning (password, g_value_get_string (value)); |
| break; |
| case PROP_DESCRIPTION: |
| g_tls_password_set_description (password, g_value_get_string (value)); |
| break; |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
| break; |
| } |
| } |
| |
| static void |
| g_tls_password_finalize (GObject *object) |
| { |
| GTlsPassword *password = G_TLS_PASSWORD (object); |
| |
| g_tls_password_real_set_value (password, NULL, 0, NULL); |
| g_free (password->priv->warning); |
| g_free (password->priv->description); |
| |
| G_OBJECT_CLASS (g_tls_password_parent_class)->finalize (object); |
| } |
| |
| static void |
| g_tls_password_class_init (GTlsPasswordClass *klass) |
| { |
| GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
| |
| klass->get_value = g_tls_password_real_get_value; |
| klass->set_value = g_tls_password_real_set_value; |
| klass->get_default_warning = g_tls_password_real_get_default_warning; |
| |
| gobject_class->get_property = g_tls_password_get_property; |
| gobject_class->set_property = g_tls_password_set_property; |
| gobject_class->finalize = g_tls_password_finalize; |
| |
| /** |
| * GTlsPassword:flags: |
| * |
| * Flags about the password. |
| * |
| * Since: 2.30 |
| */ |
| g_object_class_install_property (gobject_class, PROP_FLAGS, |
| g_param_spec_flags ("flags", NULL, NULL, |
| G_TYPE_TLS_PASSWORD_FLAGS, |
| G_TLS_PASSWORD_NONE, |
| G_PARAM_READWRITE | |
| G_PARAM_STATIC_STRINGS)); |
| |
| /** |
| * GTlsPassword:description: |
| * |
| * Description of what the password is for. |
| * |
| * Since: 2.30 |
| */ |
| g_object_class_install_property (gobject_class, PROP_DESCRIPTION, |
| g_param_spec_string ("description", NULL, NULL, |
| NULL, |
| G_PARAM_READWRITE | |
| G_PARAM_STATIC_STRINGS)); |
| |
| /** |
| * GTlsPassword:warning: |
| * |
| * Warning about the password. |
| * |
| * Since: 2.30 |
| */ |
| g_object_class_install_property (gobject_class, PROP_WARNING, |
| g_param_spec_string ("warning", NULL, NULL, |
| NULL, |
| G_PARAM_READWRITE | |
| G_PARAM_STATIC_STRINGS)); |
| |
| } |
| |
| /** |
| * g_tls_password_new: |
| * @flags: the password flags |
| * @description: description of what the password is for |
| * |
| * Create a new #GTlsPassword object. |
| * |
| * Returns: (transfer full): The newly allocated password object |
| */ |
| GTlsPassword * |
| g_tls_password_new (GTlsPasswordFlags flags, |
| const gchar *description) |
| { |
| return g_object_new (G_TYPE_TLS_PASSWORD, |
| "flags", flags, |
| "description", description, |
| NULL); |
| } |
| |
| /** |
| * g_tls_password_get_value: (virtual get_value) |
| * @password: a #GTlsPassword object |
| * @length: (optional) (out caller-allocates): location to place the length of the password. |
| * |
| * Get the password value. If @length is not %NULL then it will be |
| * filled in with the length of the password value. (Note that the |
| * password value is not nul-terminated, so you can only pass %NULL |
| * for @length in contexts where you know the password will have a |
| * certain fixed length.) |
| * |
| * Returns: (array length=length): The password value (owned by the password object). |
| * |
| * Since: 2.30 |
| */ |
| const guchar * |
| g_tls_password_get_value (GTlsPassword *password, |
| gsize *length) |
| { |
| g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL); |
| return G_TLS_PASSWORD_GET_CLASS (password)->get_value (password, length); |
| } |
| |
| /** |
| * g_tls_password_set_value: |
| * @password: a #GTlsPassword object |
| * @value: (array length=length): the new password value |
| * @length: the length of the password, or -1 |
| * |
| * Set the value for this password. The @value will be copied by the password |
| * object. |
| * |
| * Specify the @length, for a non-nul-terminated password. Pass -1 as |
| * @length if using a nul-terminated password, and @length will be |
| * calculated automatically. (Note that the terminating nul is not |
| * considered part of the password in this case.) |
| * |
| * Since: 2.30 |
| */ |
| void |
| g_tls_password_set_value (GTlsPassword *password, |
| const guchar *value, |
| gssize length) |
| { |
| g_return_if_fail (G_IS_TLS_PASSWORD (password)); |
| |
| if (length < 0) |
| { |
| /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */ |
| gsize length_unsigned = strlen ((gchar *) value); |
| g_return_if_fail (length_unsigned <= G_MAXSSIZE); |
| length = (gssize) length_unsigned; |
| } |
| |
| g_tls_password_set_value_full (password, g_memdup2 (value, (gsize) length), length, g_free); |
| } |
| |
| /** |
| * g_tls_password_set_value_full: (virtual set_value) |
| * @password: a #GTlsPassword object |
| * @value: (array length=length): the value for the password |
| * @length: the length of the password, or -1 |
| * @destroy: (nullable): a function to use to free the password. |
| * |
| * Provide the value for this password. |
| * |
| * The @value will be owned by the password object, and later freed using |
| * the @destroy function callback. |
| * |
| * Specify the @length, for a non-nul-terminated password. Pass -1 as |
| * @length if using a nul-terminated password, and @length will be |
| * calculated automatically. (Note that the terminating nul is not |
| * considered part of the password in this case.) |
| * |
| * Since: 2.30 |
| */ |
| void |
| g_tls_password_set_value_full (GTlsPassword *password, |
| guchar *value, |
| gssize length, |
| GDestroyNotify destroy) |
| { |
| g_return_if_fail (G_IS_TLS_PASSWORD (password)); |
| G_TLS_PASSWORD_GET_CLASS (password)->set_value (password, value, |
| length, destroy); |
| } |
| |
| /** |
| * g_tls_password_get_flags: |
| * @password: a #GTlsPassword object |
| * |
| * Get flags about the password. |
| * |
| * Returns: The flags about the password. |
| * |
| * Since: 2.30 |
| */ |
| GTlsPasswordFlags |
| g_tls_password_get_flags (GTlsPassword *password) |
| { |
| g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_PASSWORD_NONE); |
| return password->priv->flags; |
| } |
| |
| /** |
| * g_tls_password_set_flags: |
| * @password: a #GTlsPassword object |
| * @flags: The flags about the password |
| * |
| * Set flags about the password. |
| * |
| * Since: 2.30 |
| */ |
| void |
| g_tls_password_set_flags (GTlsPassword *password, |
| GTlsPasswordFlags flags) |
| { |
| g_return_if_fail (G_IS_TLS_PASSWORD (password)); |
| |
| password->priv->flags = flags; |
| |
| g_object_notify (G_OBJECT (password), "flags"); |
| } |
| |
| /** |
| * g_tls_password_get_description: |
| * @password: a #GTlsPassword object |
| * |
| * Get a description string about what the password will be used for. |
| * |
| * Returns: The description of the password. |
| * |
| * Since: 2.30 |
| */ |
| const gchar* |
| g_tls_password_get_description (GTlsPassword *password) |
| { |
| g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL); |
| return password->priv->description; |
| } |
| |
| /** |
| * g_tls_password_set_description: |
| * @password: a #GTlsPassword object |
| * @description: The description of the password |
| * |
| * Set a description string about what the password will be used for. |
| * |
| * Since: 2.30 |
| */ |
| void |
| g_tls_password_set_description (GTlsPassword *password, |
| const gchar *description) |
| { |
| gchar *copy; |
| |
| g_return_if_fail (G_IS_TLS_PASSWORD (password)); |
| |
| copy = g_strdup (description); |
| g_free (password->priv->description); |
| password->priv->description = copy; |
| |
| g_object_notify (G_OBJECT (password), "description"); |
| } |
| |
| /** |
| * g_tls_password_get_warning: |
| * @password: a #GTlsPassword object |
| * |
| * Get a user readable translated warning. Usually this warning is a |
| * representation of the password flags returned from |
| * g_tls_password_get_flags(). |
| * |
| * Returns: The warning. |
| * |
| * Since: 2.30 |
| */ |
| const gchar * |
| g_tls_password_get_warning (GTlsPassword *password) |
| { |
| g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL); |
| |
| if (password->priv->warning == NULL) |
| return G_TLS_PASSWORD_GET_CLASS (password)->get_default_warning (password); |
| |
| return password->priv->warning; |
| } |
| |
| /** |
| * g_tls_password_set_warning: |
| * @password: a #GTlsPassword object |
| * @warning: The user readable warning |
| * |
| * Set a user readable translated warning. Usually this warning is a |
| * representation of the password flags returned from |
| * g_tls_password_get_flags(). |
| * |
| * Since: 2.30 |
| */ |
| void |
| g_tls_password_set_warning (GTlsPassword *password, |
| const gchar *warning) |
| { |
| gchar *copy; |
| |
| g_return_if_fail (G_IS_TLS_PASSWORD (password)); |
| |
| copy = g_strdup (warning); |
| g_free (password->priv->warning); |
| password->priv->warning = copy; |
| |
| g_object_notify (G_OBJECT (password), "warning"); |
| } |