LCOV - code coverage report
Current view: top level - gcr - gcr-ssh-agent-interaction.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 117 0.0 %
Date: 2022-09-04 10:20:22 Functions: 0 15 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 26 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * gnome-keyring
       3                 :            :  *
       4                 :            :  * Copyright (C) 2018 Red Hat, Inc.
       5                 :            :  *
       6                 :            :  * This program is free software; you can redistribute it and/or modify
       7                 :            :  * it under the terms of the GNU Lesser General Public License as
       8                 :            :  * published by the Free Software Foundation; either version 2.1 of
       9                 :            :  * the License, or (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This program is distributed in the hope that it will be useful, but
      12                 :            :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14                 :            :  * Lesser General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU Lesser General Public
      17                 :            :  * License along with this program; if not, see
      18                 :            :  * <http://www.gnu.org/licenses/>.
      19                 :            :  *
      20                 :            :  * Author: Daiki Ueno
      21                 :            :  */
      22                 :            : 
      23                 :            : #include "config.h"
      24                 :            : 
      25                 :            : #include "gcr-ssh-agent-interaction.h"
      26                 :            : 
      27                 :            : #include "gcr-ssh-agent-private.h"
      28                 :            : #include "gcr-prompt.h"
      29                 :            : #include "gcr-system-prompt.h"
      30                 :            : 
      31                 :            : #include "egg/egg-secure-memory.h"
      32                 :            : #include <glib/gi18n-lib.h>
      33                 :            : #include <libsecret/secret.h>
      34                 :            : 
      35                 :            : static const SecretSchema schema = {
      36                 :            :         "org.freedesktop.Secret.Generic", SECRET_SCHEMA_NONE,
      37                 :            :         {
      38                 :            :                 { "unique", SECRET_SCHEMA_ATTRIBUTE_STRING },
      39                 :            :                 { NULL, 0 }
      40                 :            :         }
      41                 :            : };
      42                 :            : 
      43                 :            : enum {
      44                 :            :         PROP_0,
      45                 :            :         PROP_PROMPTER_NAME,
      46                 :            :         PROP_LABEL,
      47                 :            :         PROP_FIELDS
      48                 :            : };
      49                 :            : 
      50                 :            : struct _GcrSshAgentInteraction {
      51                 :            :         GTlsInteraction interaction;
      52                 :            : 
      53                 :            :         gchar *prompter_name;
      54                 :            :         gchar *label;
      55                 :            :         GHashTable *fields;
      56                 :            : };
      57                 :            : 
      58   [ #  #  #  #  :          0 : G_DEFINE_TYPE (GcrSshAgentInteraction, gcr_ssh_agent_interaction, G_TYPE_TLS_INTERACTION);
                   #  # ]
      59                 :            : 
      60                 :          0 : EGG_SECURE_DECLARE (gcr_ssh_agent_interaction);
      61                 :            : 
      62                 :            : static void
      63                 :          0 : gcr_ssh_agent_interaction_init (GcrSshAgentInteraction *self)
      64                 :            : {
      65                 :          0 : }
      66                 :            : 
      67                 :            : static void
      68                 :          0 : on_store_password_ready (GObject *source_object,
      69                 :            :                          GAsyncResult *res,
      70                 :            :                          gpointer user_data)
      71                 :            : {
      72                 :          0 :         GTask *task = G_TASK (user_data);
      73                 :          0 :         GError *error = NULL;
      74                 :            : 
      75         [ #  # ]:          0 :         if (secret_password_store_finish (res, &error)) {
      76                 :          0 :                 g_task_return_int (task, G_TLS_INTERACTION_HANDLED);
      77                 :            :         } else {
      78                 :          0 :                 g_task_return_error (task, error);
      79                 :            :         }
      80                 :          0 :         g_object_unref (task);
      81                 :          0 : }
      82                 :            : 
      83                 :            : static void
      84                 :          0 : on_prompt_password (GObject *source_object,
      85                 :            :                     GAsyncResult *result,
      86                 :            :                     gpointer user_data)
      87                 :            : {
      88                 :          0 :         GTask *task = G_TASK (user_data);
      89                 :          0 :         GcrSshAgentInteraction *self = g_task_get_source_object (task);
      90                 :          0 :         GTlsPassword *password = G_TLS_PASSWORD (g_task_get_task_data (task));
      91                 :          0 :         GcrPrompt *prompt = GCR_PROMPT (source_object);
      92                 :          0 :         GError *error = NULL;
      93                 :            :         const gchar *value;
      94                 :            :         gchar *secure_value;
      95                 :            : 
      96                 :          0 :         value = gcr_prompt_password_finish (prompt, result, &error);
      97         [ #  # ]:          0 :         if (!value) {
      98                 :          0 :                 g_object_unref (prompt);
      99         [ #  # ]:          0 :                 if (error)
     100                 :          0 :                         g_task_return_error (task, error);
     101                 :            :                 else
     102                 :          0 :                         g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, "cancelled");
     103                 :          0 :                 g_object_unref (task);
     104                 :          0 :                 return;
     105                 :            :         }
     106                 :            : 
     107                 :          0 :         secure_value = egg_secure_strndup (value, strlen (value));
     108                 :          0 :         g_tls_password_set_value_full (password,
     109                 :            :                                        (guchar *) secure_value,
     110                 :          0 :                                        strlen (secure_value),
     111                 :            :                                        (GDestroyNotify) egg_secure_free);
     112                 :            : 
     113         [ #  # ]:          0 :         if (gcr_prompt_get_choice_chosen (prompt)) {
     114                 :            :                 gchar *label;
     115                 :            : 
     116                 :          0 :                 label = g_strdup_printf (_("Unlock password for: %s"), self->label);
     117                 :          0 :                 secret_password_storev (&schema,
     118                 :            :                                         self->fields,
     119                 :            :                                         NULL,
     120                 :            :                                         label,
     121                 :            :                                         secure_value,
     122                 :            :                                         g_task_get_cancellable (task),
     123                 :            :                                         on_store_password_ready,
     124                 :            :                                         task);
     125                 :          0 :                 g_free (label);
     126                 :            :         } else {
     127                 :          0 :                 g_task_return_int (task, G_TLS_INTERACTION_HANDLED);
     128                 :          0 :                 g_object_unref (task);
     129                 :            :         }
     130                 :          0 :         g_object_unref (prompt);
     131                 :            : }
     132                 :            : 
     133                 :            : static void
     134                 :          0 : on_prompt_open (GObject *source_object,
     135                 :            :                 GAsyncResult *result,
     136                 :            :                 gpointer user_data)
     137                 :            : {
     138                 :          0 :         GTask *task = G_TASK (user_data);
     139                 :          0 :         GTlsPassword *password = g_task_get_task_data (task);
     140                 :          0 :         GError *error = NULL;
     141                 :            :         GcrPrompt *prompt;
     142                 :            :         const gchar *choice;
     143                 :            :         gchar *text;
     144                 :            : 
     145                 :          0 :         prompt = gcr_system_prompt_open_finish (result, &error);
     146         [ #  # ]:          0 :         if (!prompt) {
     147                 :          0 :                 g_task_return_error (task, error);
     148                 :          0 :                 g_object_unref (task);
     149                 :          0 :                 return;
     150                 :            :         }
     151                 :            : 
     152                 :          0 :         gcr_prompt_set_title (prompt, _("Unlock private key"));
     153                 :          0 :         gcr_prompt_set_message (prompt, _("Enter password to unlock the private key"));
     154                 :            : 
     155                 :            :         /* TRANSLATORS: The private key is locked */
     156                 :          0 :         text = g_strdup_printf (_("An application wants access to the private key “%s”, but it is locked"),
     157                 :            :                                 g_tls_password_get_description (password));
     158                 :          0 :         gcr_prompt_set_description (prompt, text);
     159                 :          0 :         g_free (text);
     160                 :            : 
     161                 :          0 :         choice = _("Automatically unlock this key whenever I’m logged in");
     162                 :          0 :         gcr_prompt_set_choice_label (prompt, choice);
     163                 :          0 :         gcr_prompt_set_continue_label (prompt, _("Unlock"));
     164                 :            : 
     165         [ #  # ]:          0 :         if (g_tls_password_get_flags (password) & G_TLS_PASSWORD_RETRY)
     166                 :          0 :                 gcr_prompt_set_warning (prompt, _("The unlock password was incorrect"));
     167                 :            : 
     168                 :          0 :         gcr_prompt_password_async (prompt, g_task_get_cancellable (task), on_prompt_password, task);
     169                 :            : }
     170                 :            : 
     171                 :            : static void
     172                 :          0 : on_lookup_password_ready (GObject *source_object,
     173                 :            :                           GAsyncResult *res,
     174                 :            :                           gpointer user_data)
     175                 :            : {
     176                 :          0 :         GTask *task = G_TASK (user_data);
     177                 :          0 :         GcrSshAgentInteraction *self = g_task_get_source_object (task);
     178                 :          0 :         GTlsPassword *password = G_TLS_PASSWORD (g_task_get_task_data (task));
     179                 :          0 :         GError *error = NULL;
     180                 :            : 
     181                 :          0 :         gchar *value = secret_password_lookup_finish (res, &error);
     182         [ #  # ]:          0 :         if (value) {
     183                 :            :                 /* If password is found in the login keyring, return it */
     184                 :          0 :                 g_tls_password_set_value_full (password,
     185                 :          0 :                                                (guchar *)value, strlen (value),
     186                 :            :                                                (GDestroyNotify)egg_secure_free);
     187                 :          0 :                 g_task_return_int (task, G_TLS_INTERACTION_HANDLED);
     188                 :          0 :                 g_object_unref (task);
     189                 :            :         } else {
     190                 :            :                 /* Otherwise, prompt a password */
     191                 :          0 :                 gcr_system_prompt_open_for_prompter_async (self->prompter_name, 60,
     192                 :            :                                                            g_task_get_cancellable (task),
     193                 :            :                                                            on_prompt_open,
     194                 :            :                                                            task);
     195                 :            :         }
     196                 :          0 : }
     197                 :            : 
     198                 :            : static void
     199                 :          0 : gcr_ssh_agent_interaction_ask_password_async (GTlsInteraction *interaction,
     200                 :            :                                               GTlsPassword *password,
     201                 :            :                                               GCancellable *cancellable,
     202                 :            :                                               GAsyncReadyCallback callback,
     203                 :            :                                               gpointer user_data)
     204                 :            : {
     205                 :          0 :         GcrSshAgentInteraction *self = GCR_SSH_AGENT_INTERACTION (interaction);
     206                 :            :         GTask *task;
     207                 :            : 
     208                 :          0 :         task = g_task_new (interaction, cancellable, callback, user_data);
     209                 :          0 :         g_task_set_task_data (task, g_object_ref (password), g_object_unref);
     210                 :            : 
     211                 :          0 :         secret_password_lookupv (&schema,
     212                 :            :                                  self->fields,
     213                 :            :                                  cancellable,
     214                 :            :                                  on_lookup_password_ready,
     215                 :            :                                  task);
     216                 :          0 : }
     217                 :            : 
     218                 :            : static GTlsInteractionResult
     219                 :          0 : gcr_ssh_agent_interaction_ask_password_finish (GTlsInteraction *interaction,
     220                 :            :                                                GAsyncResult *res,
     221                 :            :                                                GError **error)
     222                 :            : {
     223                 :          0 :         GTask *task = G_TASK (res);
     224                 :            :         GTlsInteractionResult result;
     225                 :            : 
     226                 :          0 :         result = g_task_propagate_int (task, error);
     227         [ #  # ]:          0 :         if (result == -1)
     228                 :          0 :                 return G_TLS_INTERACTION_FAILED;
     229                 :          0 :         return result;
     230                 :            : }
     231                 :            : 
     232                 :            : static void
     233                 :          0 : gcr_ssh_agent_interaction_set_property (GObject *object,
     234                 :            :                                         guint prop_id,
     235                 :            :                                         const GValue *value,
     236                 :            :                                         GParamSpec *pspec)
     237                 :            : {
     238                 :          0 :         GcrSshAgentInteraction *self = GCR_SSH_AGENT_INTERACTION (object);
     239                 :            : 
     240   [ #  #  #  # ]:          0 :         switch (prop_id) {
     241                 :          0 :         case PROP_PROMPTER_NAME:
     242                 :          0 :                 self->prompter_name = g_value_dup_string (value);
     243                 :          0 :                 break;
     244                 :          0 :         case PROP_LABEL:
     245                 :          0 :                 self->label = g_value_dup_string (value);
     246                 :          0 :                 break;
     247                 :          0 :         case PROP_FIELDS:
     248                 :          0 :                 self->fields = g_value_dup_boxed (value);
     249                 :          0 :                 break;
     250                 :          0 :         default:
     251                 :          0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     252                 :          0 :                 break;
     253                 :            :         }
     254                 :          0 : }
     255                 :            : 
     256                 :            : static void
     257                 :          0 : gcr_ssh_agent_interaction_finalize (GObject *object)
     258                 :            : {
     259                 :          0 :         GcrSshAgentInteraction *self = GCR_SSH_AGENT_INTERACTION (object);
     260                 :            : 
     261                 :          0 :         g_free (self->prompter_name);
     262                 :          0 :         g_free (self->label);
     263                 :          0 :         g_hash_table_unref (self->fields);
     264                 :            : 
     265                 :          0 :         G_OBJECT_CLASS (gcr_ssh_agent_interaction_parent_class)->finalize (object);
     266                 :          0 : }
     267                 :            : 
     268                 :            : static void
     269                 :          0 : gcr_ssh_agent_interaction_class_init (GcrSshAgentInteractionClass *klass)
     270                 :            : {
     271                 :          0 :         GTlsInteractionClass *interaction_class = G_TLS_INTERACTION_CLASS (klass);
     272                 :          0 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     273                 :            : 
     274                 :          0 :         interaction_class->ask_password_async = gcr_ssh_agent_interaction_ask_password_async;
     275                 :          0 :         interaction_class->ask_password_finish = gcr_ssh_agent_interaction_ask_password_finish;
     276                 :            : 
     277                 :          0 :         gobject_class->set_property = gcr_ssh_agent_interaction_set_property;
     278                 :          0 :         gobject_class->finalize = gcr_ssh_agent_interaction_finalize;
     279                 :            : 
     280                 :          0 :         g_object_class_install_property (gobject_class, PROP_PROMPTER_NAME,
     281                 :            :                                          g_param_spec_string ("prompter-name", "Prompter-name", "Prompter-name",
     282                 :            :                                                               NULL,
     283                 :            :                                                               G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
     284                 :          0 :         g_object_class_install_property (gobject_class, PROP_LABEL,
     285                 :            :                                          g_param_spec_string ("label", "Label", "Label",
     286                 :            :                                                               "",
     287                 :            :                                                               G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
     288                 :          0 :         g_object_class_install_property (gobject_class, PROP_FIELDS,
     289                 :            :                                          g_param_spec_boxed ("fields", "Fields", "Fields",
     290                 :            :                                                              G_TYPE_HASH_TABLE,
     291                 :            :                                                              G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
     292                 :          0 : }
     293                 :            : 
     294                 :            : GTlsInteraction *
     295                 :          0 : gcr_ssh_agent_interaction_new (const gchar *prompter_name,
     296                 :            :                                const gchar *label,
     297                 :            :                                GHashTable *fields)
     298                 :            : {
     299                 :          0 :         return g_object_new (GCR_TYPE_SSH_AGENT_INTERACTION,
     300                 :            :                              "prompter-name", prompter_name,
     301                 :            :                              "label", label,
     302                 :            :                              "fields", fields,
     303                 :            :                              NULL);
     304                 :            : }

Generated by: LCOV version 1.14