LCOV - code coverage report
Current view: top level - gio - gtlsinteraction.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 100.0 % 217 217
Test Date: 2024-11-26 05:23:01 Functions: 100.0 % 25 25
Branches: - 0 0

             Branch data     Line data    Source code
       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                 :             : 
      25                 :             : #include <string.h>
      26                 :             : 
      27                 :             : #include "gtlscertificate.h"
      28                 :             : #include "gtlsconnection.h"
      29                 :             : #include "gtlsinteraction.h"
      30                 :             : #include "gtlspassword.h"
      31                 :             : #include "gasyncresult.h"
      32                 :             : #include "gcancellable.h"
      33                 :             : #include "gtask.h"
      34                 :             : #include "gioenumtypes.h"
      35                 :             : #include "glibintl.h"
      36                 :             : 
      37                 :             : 
      38                 :             : /**
      39                 :             :  * GTlsInteraction:
      40                 :             :  *
      41                 :             :  * `GTlsInteraction` provides a mechanism for the TLS connection and database
      42                 :             :  * code to interact with the user. It can be used to ask the user for passwords.
      43                 :             :  *
      44                 :             :  * To use a `GTlsInteraction` with a TLS connection use
      45                 :             :  * [method@Gio.TlsConnection.set_interaction].
      46                 :             :  *
      47                 :             :  * Callers should instantiate a derived class that implements the various
      48                 :             :  * interaction methods to show the required dialogs.
      49                 :             :  *
      50                 :             :  * Callers should use the 'invoke' functions like
      51                 :             :  * [method@Gio.TlsInteraction.invoke_ask_password] to run interaction methods.
      52                 :             :  * These functions make sure that the interaction is invoked in the main loop
      53                 :             :  * and not in the current thread, if the current thread is not running the
      54                 :             :  * main loop.
      55                 :             :  *
      56                 :             :  * Derived classes can choose to implement whichever interactions methods they’d
      57                 :             :  * like to support by overriding those virtual methods in their class
      58                 :             :  * initialization function. Any interactions not implemented will return
      59                 :             :  * `G_TLS_INTERACTION_UNHANDLED`. If a derived class implements an async method,
      60                 :             :  * it must also implement the corresponding finish method.
      61                 :             :  *
      62                 :             :  * Since: 2.30
      63                 :             :  */
      64                 :             : 
      65                 :             : /**
      66                 :             :  * GTlsInteractionClass:
      67                 :             :  * @ask_password: ask for a password synchronously. If the implementation
      68                 :             :  *     returns %G_TLS_INTERACTION_HANDLED, then the password argument should
      69                 :             :  *     have been filled in by using g_tls_password_set_value() or a similar
      70                 :             :  *     function.
      71                 :             :  * @ask_password_async: ask for a password asynchronously.
      72                 :             :  * @ask_password_finish: complete operation to ask for a password asynchronously.
      73                 :             :  *     If the implementation returns %G_TLS_INTERACTION_HANDLED, then the
      74                 :             :  *     password argument of the async method should have been filled in by using
      75                 :             :  *     g_tls_password_set_value() or a similar function.
      76                 :             :  * @request_certificate: ask for a certificate synchronously. If the
      77                 :             :  *     implementation returns %G_TLS_INTERACTION_HANDLED, then the connection
      78                 :             :  *     argument should have been filled in by using
      79                 :             :  *     g_tls_connection_set_certificate().
      80                 :             :  * @request_certificate_async: ask for a certificate asynchronously.
      81                 :             :  * @request_certificate_finish: complete operation to ask for a certificate
      82                 :             :  *     asynchronously. If the implementation returns %G_TLS_INTERACTION_HANDLED,
      83                 :             :  *     then the connection argument of the async method should have been
      84                 :             :  *     filled in by using g_tls_connection_set_certificate().
      85                 :             :  *
      86                 :             :  * The class for #GTlsInteraction. Derived classes implement the various
      87                 :             :  * virtual interaction methods to handle TLS interactions.
      88                 :             :  *
      89                 :             :  * Derived classes can choose to implement whichever interactions methods they'd
      90                 :             :  * like to support by overriding those virtual methods in their class
      91                 :             :  * initialization function. If a derived class implements an async method,
      92                 :             :  * it must also implement the corresponding finish method.
      93                 :             :  *
      94                 :             :  * The synchronous interaction methods should implement to display modal dialogs,
      95                 :             :  * and the asynchronous methods to display modeless dialogs.
      96                 :             :  *
      97                 :             :  * If the user cancels an interaction, then the result should be
      98                 :             :  * %G_TLS_INTERACTION_FAILED and the error should be set with a domain of
      99                 :             :  * %G_IO_ERROR and code of %G_IO_ERROR_CANCELLED.
     100                 :             :  *
     101                 :             :  * Since: 2.30
     102                 :             :  */
     103                 :             : 
     104                 :             : struct _GTlsInteractionPrivate {
     105                 :             :   GMainContext *context;
     106                 :             : };
     107                 :             : 
     108                 :         162 : G_DEFINE_TYPE_WITH_PRIVATE (GTlsInteraction, g_tls_interaction, G_TYPE_OBJECT)
     109                 :             : 
     110                 :             : typedef struct {
     111                 :             :   GMutex mutex;
     112                 :             : 
     113                 :             :   /* Input arguments */
     114                 :             :   GTlsInteraction *interaction;
     115                 :             :   GObject *argument;
     116                 :             :   GCancellable *cancellable;
     117                 :             : 
     118                 :             :   /* Used when we're invoking async interactions */
     119                 :             :   GAsyncReadyCallback callback;
     120                 :             :   gpointer user_data;
     121                 :             : 
     122                 :             :   /* Used when we expect results */
     123                 :             :   GTlsInteractionResult result;
     124                 :             :   GError *error;
     125                 :             :   gboolean complete;
     126                 :             :   GCond cond;
     127                 :             : } InvokeClosure;
     128                 :             : 
     129                 :             : static void
     130                 :          24 : invoke_closure_free (gpointer data)
     131                 :             : {
     132                 :          24 :   InvokeClosure *closure = data;
     133                 :          24 :   g_assert (closure);
     134                 :          24 :   g_object_unref (closure->interaction);
     135                 :          24 :   g_clear_object (&closure->argument);
     136                 :          24 :   g_clear_object (&closure->cancellable);
     137                 :          24 :   g_cond_clear (&closure->cond);
     138                 :          24 :   g_mutex_clear (&closure->mutex);
     139                 :          24 :   g_clear_error (&closure->error);
     140                 :             : 
     141                 :             :   /* Insurance that we've actually used these before freeing */
     142                 :          24 :   g_assert (closure->callback == NULL);
     143                 :          24 :   g_assert (closure->user_data == NULL);
     144                 :             : 
     145                 :          24 :   g_free (closure);
     146                 :          24 : }
     147                 :             : 
     148                 :             : static InvokeClosure *
     149                 :          24 : invoke_closure_new (GTlsInteraction *interaction,
     150                 :             :                     GObject         *argument,
     151                 :             :                     GCancellable    *cancellable)
     152                 :             : {
     153                 :          24 :   InvokeClosure *closure = g_new0 (InvokeClosure, 1);
     154                 :          24 :   closure->interaction = g_object_ref (interaction);
     155                 :          24 :   closure->argument = argument ? g_object_ref (argument) : NULL;
     156                 :          24 :   closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
     157                 :          24 :   g_mutex_init (&closure->mutex);
     158                 :          24 :   g_cond_init (&closure->cond);
     159                 :          24 :   closure->result = G_TLS_INTERACTION_UNHANDLED;
     160                 :          24 :   return closure;
     161                 :             : }
     162                 :             : 
     163                 :             : static GTlsInteractionResult
     164                 :          16 : invoke_closure_wait_and_free (InvokeClosure *closure,
     165                 :             :                               GError       **error)
     166                 :             : {
     167                 :             :   GTlsInteractionResult result;
     168                 :             : 
     169                 :          16 :   g_mutex_lock (&closure->mutex);
     170                 :             : 
     171                 :          24 :   while (!closure->complete)
     172                 :           8 :     g_cond_wait (&closure->cond, &closure->mutex);
     173                 :             : 
     174                 :          16 :   g_mutex_unlock (&closure->mutex);
     175                 :             : 
     176                 :          16 :   if (closure->error)
     177                 :             :     {
     178                 :           8 :       g_propagate_error (error, closure->error);
     179                 :           8 :       closure->error = NULL;
     180                 :             :     }
     181                 :          16 :   result = closure->result;
     182                 :             : 
     183                 :          16 :   invoke_closure_free (closure);
     184                 :          16 :   return result;
     185                 :             : }
     186                 :             : 
     187                 :             : static GTlsInteractionResult
     188                 :          12 : invoke_closure_complete_and_free (GTlsInteraction *interaction,
     189                 :             :                                   InvokeClosure *closure,
     190                 :             :                                   GError **error)
     191                 :             : {
     192                 :             :   GTlsInteractionResult result;
     193                 :             :   gboolean complete;
     194                 :             : 
     195                 :             :   /*
     196                 :             :    * Handle the case where we've been called from within the main context
     197                 :             :    * or in the case where the main context is not running. This approximates
     198                 :             :    * the behavior of a modal dialog.
     199                 :             :    */
     200                 :          12 :   if (g_main_context_acquire (interaction->priv->context))
     201                 :             :     {
     202                 :             :       for (;;)
     203                 :             :         {
     204                 :          16 :           g_mutex_lock (&closure->mutex);
     205                 :          16 :           complete = closure->complete;
     206                 :          16 :           g_mutex_unlock (&closure->mutex);
     207                 :          16 :           if (complete)
     208                 :           8 :             break;
     209                 :           8 :           g_main_context_iteration (interaction->priv->context, TRUE);
     210                 :             :         }
     211                 :             : 
     212                 :           8 :       g_main_context_release (interaction->priv->context);
     213                 :             : 
     214                 :           8 :       if (closure->error)
     215                 :             :         {
     216                 :           4 :           g_propagate_error (error, closure->error);
     217                 :           4 :           closure->error = NULL;
     218                 :             :         }
     219                 :             : 
     220                 :           8 :       result = closure->result;
     221                 :           8 :       invoke_closure_free (closure);
     222                 :             :     }
     223                 :             : 
     224                 :             :   /*
     225                 :             :    * Handle the case where we're in a different thread than the main
     226                 :             :    * context and a main loop is running.
     227                 :             :    */
     228                 :             :   else
     229                 :             :     {
     230                 :           4 :       result = invoke_closure_wait_and_free (closure, error);
     231                 :             :     }
     232                 :             : 
     233                 :          12 :   return result;
     234                 :             : }
     235                 :             : 
     236                 :             : static void
     237                 :          43 : g_tls_interaction_init (GTlsInteraction *interaction)
     238                 :             : {
     239                 :          43 :   interaction->priv = g_tls_interaction_get_instance_private (interaction);
     240                 :          43 :   interaction->priv->context = g_main_context_ref_thread_default ();
     241                 :          43 : }
     242                 :             : 
     243                 :             : static void
     244                 :          43 : g_tls_interaction_finalize (GObject *object)
     245                 :             : {
     246                 :          43 :   GTlsInteraction *interaction = G_TLS_INTERACTION (object);
     247                 :             : 
     248                 :          43 :   g_main_context_unref (interaction->priv->context);
     249                 :             : 
     250                 :          43 :   G_OBJECT_CLASS (g_tls_interaction_parent_class)->finalize (object);
     251                 :          43 : }
     252                 :             : 
     253                 :             : static void
     254                 :           3 : g_tls_interaction_class_init (GTlsInteractionClass *klass)
     255                 :             : {
     256                 :           3 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     257                 :             : 
     258                 :           3 :   gobject_class->finalize = g_tls_interaction_finalize;
     259                 :           3 : }
     260                 :             : 
     261                 :             : static gboolean
     262                 :           6 : on_invoke_ask_password_sync (gpointer user_data)
     263                 :             : {
     264                 :           6 :   InvokeClosure *closure = user_data;
     265                 :             :   GTlsInteractionClass *klass;
     266                 :             : 
     267                 :           6 :   g_mutex_lock (&closure->mutex);
     268                 :             : 
     269                 :           6 :   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
     270                 :           6 :   g_assert (klass->ask_password);
     271                 :             : 
     272                 :           6 :   closure->result = klass->ask_password (closure->interaction,
     273                 :           6 :                                          G_TLS_PASSWORD (closure->argument),
     274                 :             :                                          closure->cancellable,
     275                 :             :                                          &closure->error);
     276                 :             : 
     277                 :           6 :   closure->complete = TRUE;
     278                 :           6 :   g_cond_signal (&closure->cond);
     279                 :           6 :   g_mutex_unlock (&closure->mutex);
     280                 :             : 
     281                 :           6 :   return FALSE; /* don't call again */
     282                 :             : }
     283                 :             : 
     284                 :             : static void
     285                 :           6 : on_ask_password_complete (GObject      *source,
     286                 :             :                           GAsyncResult *result,
     287                 :             :                           gpointer      user_data)
     288                 :             : {
     289                 :           6 :   InvokeClosure *closure = user_data;
     290                 :             :   GTlsInteractionClass *klass;
     291                 :             : 
     292                 :           6 :   g_mutex_lock (&closure->mutex);
     293                 :             : 
     294                 :           6 :   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
     295                 :           6 :   g_assert (klass->ask_password_finish);
     296                 :             : 
     297                 :           6 :   closure->result = klass->ask_password_finish (closure->interaction,
     298                 :             :                                                 result,
     299                 :             :                                                 &closure->error);
     300                 :             : 
     301                 :           6 :   closure->complete = TRUE;
     302                 :           6 :   g_cond_signal (&closure->cond);
     303                 :           6 :   g_mutex_unlock (&closure->mutex);
     304                 :           6 : }
     305                 :             : 
     306                 :             : static gboolean
     307                 :           6 : on_invoke_ask_password_async_as_sync (gpointer user_data)
     308                 :             : {
     309                 :           6 :   InvokeClosure *closure = user_data;
     310                 :             :   GTlsInteractionClass *klass;
     311                 :             : 
     312                 :           6 :   g_mutex_lock (&closure->mutex);
     313                 :             : 
     314                 :           6 :   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
     315                 :           6 :   g_assert (klass->ask_password_async);
     316                 :             : 
     317                 :           6 :   klass->ask_password_async (closure->interaction,
     318                 :           6 :                              G_TLS_PASSWORD (closure->argument),
     319                 :             :                              closure->cancellable,
     320                 :             :                              on_ask_password_complete,
     321                 :             :                              closure);
     322                 :             : 
     323                 :             :   /* Note that we've used these */
     324                 :           6 :   closure->callback = NULL;
     325                 :           6 :   closure->user_data = NULL;
     326                 :             : 
     327                 :           6 :   g_mutex_unlock (&closure->mutex);
     328                 :             : 
     329                 :           6 :   return FALSE; /* don't call again */
     330                 :             : }
     331                 :             : 
     332                 :             : /**
     333                 :             :  * g_tls_interaction_invoke_ask_password:
     334                 :             :  * @interaction: a #GTlsInteraction object
     335                 :             :  * @password: a #GTlsPassword object
     336                 :             :  * @cancellable: an optional #GCancellable cancellation object
     337                 :             :  * @error: an optional location to place an error on failure
     338                 :             :  *
     339                 :             :  * Invoke the interaction to ask the user for a password. It invokes this
     340                 :             :  * interaction in the main loop, specifically the #GMainContext returned by
     341                 :             :  * g_main_context_get_thread_default() when the interaction is created. This
     342                 :             :  * is called by called by #GTlsConnection or #GTlsDatabase to ask the user
     343                 :             :  * for a password.
     344                 :             :  *
     345                 :             :  * Derived subclasses usually implement a password prompt, although they may
     346                 :             :  * also choose to provide a password from elsewhere. The @password value will
     347                 :             :  * be filled in and then @callback will be called. Alternatively the user may
     348                 :             :  * abort this password request, which will usually abort the TLS connection.
     349                 :             :  *
     350                 :             :  * The implementation can either be a synchronous (eg: modal dialog) or an
     351                 :             :  * asynchronous one (eg: modeless dialog). This function will take care of
     352                 :             :  * calling which ever one correctly.
     353                 :             :  *
     354                 :             :  * If the interaction is cancelled by the cancellation object, or by the
     355                 :             :  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
     356                 :             :  * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
     357                 :             :  * not support immediate cancellation.
     358                 :             :  *
     359                 :             :  * Returns: The status of the ask password interaction.
     360                 :             :  *
     361                 :             :  * Since: 2.30
     362                 :             :  */
     363                 :             : GTlsInteractionResult
     364                 :          15 : g_tls_interaction_invoke_ask_password (GTlsInteraction    *interaction,
     365                 :             :                                        GTlsPassword       *password,
     366                 :             :                                        GCancellable       *cancellable,
     367                 :             :                                        GError            **error)
     368                 :             : {
     369                 :             :   GTlsInteractionResult result;
     370                 :             :   InvokeClosure *closure;
     371                 :             :   GTlsInteractionClass *klass;
     372                 :             : 
     373                 :          15 :   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
     374                 :          15 :   g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_INTERACTION_UNHANDLED);
     375                 :          15 :   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
     376                 :             : 
     377                 :          15 :   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
     378                 :             : 
     379                 :          15 :   if (klass->ask_password)
     380                 :             :     {
     381                 :           6 :       closure = invoke_closure_new (interaction, G_OBJECT (password), cancellable);
     382                 :           6 :       g_main_context_invoke (interaction->priv->context,
     383                 :             :                              on_invoke_ask_password_sync, closure);
     384                 :           6 :       result = invoke_closure_wait_and_free (closure, error);
     385                 :             :     }
     386                 :           9 :   else if (klass->ask_password_async)
     387                 :             :     {
     388                 :           6 :       g_return_val_if_fail (klass->ask_password_finish, G_TLS_INTERACTION_UNHANDLED);
     389                 :             : 
     390                 :           6 :       closure = invoke_closure_new (interaction, G_OBJECT (password), cancellable);
     391                 :           6 :       g_main_context_invoke (interaction->priv->context,
     392                 :             :                              on_invoke_ask_password_async_as_sync, closure);
     393                 :             : 
     394                 :           6 :       result = invoke_closure_complete_and_free (interaction, closure, error);
     395                 :             :     }
     396                 :             :   else
     397                 :             :     {
     398                 :           3 :       result = G_TLS_INTERACTION_UNHANDLED;
     399                 :             :     }
     400                 :             : 
     401                 :          15 :   return result;
     402                 :             : }
     403                 :             : 
     404                 :             : /**
     405                 :             :  * g_tls_interaction_ask_password:
     406                 :             :  * @interaction: a #GTlsInteraction object
     407                 :             :  * @password: a #GTlsPassword object
     408                 :             :  * @cancellable: an optional #GCancellable cancellation object
     409                 :             :  * @error: an optional location to place an error on failure
     410                 :             :  *
     411                 :             :  * Run synchronous interaction to ask the user for a password. In general,
     412                 :             :  * g_tls_interaction_invoke_ask_password() should be used instead of this
     413                 :             :  * function.
     414                 :             :  *
     415                 :             :  * Derived subclasses usually implement a password prompt, although they may
     416                 :             :  * also choose to provide a password from elsewhere. The @password value will
     417                 :             :  * be filled in and then @callback will be called. Alternatively the user may
     418                 :             :  * abort this password request, which will usually abort the TLS connection.
     419                 :             :  *
     420                 :             :  * If the interaction is cancelled by the cancellation object, or by the
     421                 :             :  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
     422                 :             :  * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
     423                 :             :  * not support immediate cancellation.
     424                 :             :  *
     425                 :             :  * Returns: The status of the ask password interaction.
     426                 :             :  *
     427                 :             :  * Since: 2.30
     428                 :             :  */
     429                 :             : GTlsInteractionResult
     430                 :           3 : g_tls_interaction_ask_password (GTlsInteraction    *interaction,
     431                 :             :                                 GTlsPassword       *password,
     432                 :             :                                 GCancellable       *cancellable,
     433                 :             :                                 GError            **error)
     434                 :             : {
     435                 :             :   GTlsInteractionClass *klass;
     436                 :             : 
     437                 :           3 :   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
     438                 :           3 :   g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_INTERACTION_UNHANDLED);
     439                 :           3 :   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
     440                 :             : 
     441                 :           3 :   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
     442                 :           3 :   if (klass->ask_password)
     443                 :           2 :     return (klass->ask_password) (interaction, password, cancellable, error);
     444                 :             :   else
     445                 :           1 :     return G_TLS_INTERACTION_UNHANDLED;
     446                 :             : }
     447                 :             : 
     448                 :             : /**
     449                 :             :  * g_tls_interaction_ask_password_async:
     450                 :             :  * @interaction: a #GTlsInteraction object
     451                 :             :  * @password: a #GTlsPassword object
     452                 :             :  * @cancellable: an optional #GCancellable cancellation object
     453                 :             :  * @callback: (nullable): will be called when the interaction completes
     454                 :             :  * @user_data: (nullable): data to pass to the @callback
     455                 :             :  *
     456                 :             :  * Run asynchronous interaction to ask the user for a password. In general,
     457                 :             :  * g_tls_interaction_invoke_ask_password() should be used instead of this
     458                 :             :  * function.
     459                 :             :  *
     460                 :             :  * Derived subclasses usually implement a password prompt, although they may
     461                 :             :  * also choose to provide a password from elsewhere. The @password value will
     462                 :             :  * be filled in and then @callback will be called. Alternatively the user may
     463                 :             :  * abort this password request, which will usually abort the TLS connection.
     464                 :             :  *
     465                 :             :  * If the interaction is cancelled by the cancellation object, or by the
     466                 :             :  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
     467                 :             :  * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
     468                 :             :  * not support immediate cancellation.
     469                 :             :  *
     470                 :             :  * Certain implementations may not support immediate cancellation.
     471                 :             :  *
     472                 :             :  * Since: 2.30
     473                 :             :  */
     474                 :             : void
     475                 :           3 : g_tls_interaction_ask_password_async (GTlsInteraction    *interaction,
     476                 :             :                                       GTlsPassword       *password,
     477                 :             :                                       GCancellable       *cancellable,
     478                 :             :                                       GAsyncReadyCallback callback,
     479                 :             :                                       gpointer            user_data)
     480                 :             : {
     481                 :             :   GTlsInteractionClass *klass;
     482                 :             :   GTask *task;
     483                 :             : 
     484                 :           3 :   g_return_if_fail (G_IS_TLS_INTERACTION (interaction));
     485                 :           3 :   g_return_if_fail (G_IS_TLS_PASSWORD (password));
     486                 :           3 :   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
     487                 :             : 
     488                 :           3 :   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
     489                 :           3 :   if (klass->ask_password_async)
     490                 :             :     {
     491                 :           2 :       g_return_if_fail (klass->ask_password_finish);
     492                 :           2 :       (klass->ask_password_async) (interaction, password, cancellable,
     493                 :             :                                    callback, user_data);
     494                 :             :     }
     495                 :             :   else
     496                 :             :     {
     497                 :           1 :       task = g_task_new (interaction, cancellable, callback, user_data);
     498                 :           1 :       g_task_set_source_tag (task, g_tls_interaction_ask_password_async);
     499                 :           1 :       g_task_return_int (task, G_TLS_INTERACTION_UNHANDLED);
     500                 :           1 :       g_object_unref (task);
     501                 :             :     }
     502                 :             : }
     503                 :             : 
     504                 :             : /**
     505                 :             :  * g_tls_interaction_ask_password_finish:
     506                 :             :  * @interaction: a #GTlsInteraction object
     507                 :             :  * @result: the result passed to the callback
     508                 :             :  * @error: an optional location to place an error on failure
     509                 :             :  *
     510                 :             :  * Complete an ask password user interaction request. This should be once
     511                 :             :  * the g_tls_interaction_ask_password_async() completion callback is called.
     512                 :             :  *
     513                 :             :  * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsPassword passed
     514                 :             :  * to g_tls_interaction_ask_password() will have its password filled in.
     515                 :             :  *
     516                 :             :  * If the interaction is cancelled by the cancellation object, or by the
     517                 :             :  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
     518                 :             :  * contains a %G_IO_ERROR_CANCELLED error code.
     519                 :             :  *
     520                 :             :  * Returns: The status of the ask password interaction.
     521                 :             :  *
     522                 :             :  * Since: 2.30
     523                 :             :  */
     524                 :             : GTlsInteractionResult
     525                 :           3 : g_tls_interaction_ask_password_finish (GTlsInteraction    *interaction,
     526                 :             :                                        GAsyncResult       *result,
     527                 :             :                                        GError            **error)
     528                 :             : {
     529                 :             :   GTlsInteractionClass *klass;
     530                 :             : 
     531                 :           3 :   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
     532                 :           3 :   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), G_TLS_INTERACTION_UNHANDLED);
     533                 :             : 
     534                 :           3 :   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
     535                 :           3 :   if (klass->ask_password_finish)
     536                 :             :     {
     537                 :           2 :       g_return_val_if_fail (klass->ask_password_async != NULL, G_TLS_INTERACTION_UNHANDLED);
     538                 :             : 
     539                 :           2 :       return (klass->ask_password_finish) (interaction, result, error);
     540                 :             :     }
     541                 :             :   else
     542                 :             :     {
     543                 :           1 :       g_return_val_if_fail (g_async_result_is_tagged (result, g_tls_interaction_ask_password_async), G_TLS_INTERACTION_UNHANDLED);
     544                 :             : 
     545                 :           1 :       return g_task_propagate_int (G_TASK (result), error);
     546                 :             :     }
     547                 :             : }
     548                 :             : 
     549                 :             : static gboolean
     550                 :           6 : on_invoke_request_certificate_sync (gpointer user_data)
     551                 :             : {
     552                 :           6 :   InvokeClosure *closure = user_data;
     553                 :             :   GTlsInteractionClass *klass;
     554                 :             : 
     555                 :           6 :   g_mutex_lock (&closure->mutex);
     556                 :             : 
     557                 :           6 :   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
     558                 :           6 :   g_assert (klass->request_certificate != NULL);
     559                 :             : 
     560                 :           6 :   closure->result = klass->request_certificate (closure->interaction,
     561                 :           6 :                                                 G_TLS_CONNECTION (closure->argument),
     562                 :             :                                                 0,
     563                 :             :                                                 closure->cancellable,
     564                 :             :                                                 &closure->error);
     565                 :             : 
     566                 :           6 :   closure->complete = TRUE;
     567                 :           6 :   g_cond_signal (&closure->cond);
     568                 :           6 :   g_mutex_unlock (&closure->mutex);
     569                 :             : 
     570                 :           6 :   return FALSE; /* don't call again */
     571                 :             : }
     572                 :             : 
     573                 :             : static void
     574                 :           6 : on_request_certificate_complete (GObject      *source,
     575                 :             :                                  GAsyncResult *result,
     576                 :             :                                  gpointer      user_data)
     577                 :             : {
     578                 :           6 :   InvokeClosure *closure = user_data;
     579                 :             :   GTlsInteractionClass *klass;
     580                 :             : 
     581                 :           6 :   g_mutex_lock (&closure->mutex);
     582                 :             : 
     583                 :           6 :   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
     584                 :           6 :   g_assert (klass->request_certificate_finish != NULL);
     585                 :             : 
     586                 :           6 :   closure->result = klass->request_certificate_finish (closure->interaction,
     587                 :             :                                                        result, &closure->error);
     588                 :             : 
     589                 :           6 :   closure->complete = TRUE;
     590                 :           6 :   g_cond_signal (&closure->cond);
     591                 :           6 :   g_mutex_unlock (&closure->mutex);
     592                 :           6 : }
     593                 :             : 
     594                 :             : static gboolean
     595                 :           6 : on_invoke_request_certificate_async_as_sync (gpointer user_data)
     596                 :             : {
     597                 :           6 :   InvokeClosure *closure = user_data;
     598                 :             :   GTlsInteractionClass *klass;
     599                 :             : 
     600                 :           6 :   g_mutex_lock (&closure->mutex);
     601                 :             : 
     602                 :           6 :   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
     603                 :           6 :   g_assert (klass->request_certificate_async);
     604                 :             : 
     605                 :           6 :   klass->request_certificate_async (closure->interaction,
     606                 :           6 :                                     G_TLS_CONNECTION (closure->argument), 0,
     607                 :             :                                     closure->cancellable,
     608                 :             :                                     on_request_certificate_complete,
     609                 :             :                                     closure);
     610                 :             : 
     611                 :             :   /* Note that we've used these */
     612                 :           6 :   closure->callback = NULL;
     613                 :           6 :   closure->user_data = NULL;
     614                 :             : 
     615                 :           6 :   g_mutex_unlock (&closure->mutex);
     616                 :             : 
     617                 :           6 :   return FALSE; /* don't call again */
     618                 :             : }
     619                 :             : 
     620                 :             : /**
     621                 :             :  * g_tls_interaction_invoke_request_certificate:
     622                 :             :  * @interaction: a #GTlsInteraction object
     623                 :             :  * @connection: a #GTlsConnection object
     624                 :             :  * @flags: flags providing more information about the request
     625                 :             :  * @cancellable: an optional #GCancellable cancellation object
     626                 :             :  * @error: an optional location to place an error on failure
     627                 :             :  *
     628                 :             :  * Invoke the interaction to ask the user to choose a certificate to
     629                 :             :  * use with the connection. It invokes this interaction in the main
     630                 :             :  * loop, specifically the #GMainContext returned by
     631                 :             :  * g_main_context_get_thread_default() when the interaction is
     632                 :             :  * created. This is called by called by #GTlsConnection when the peer
     633                 :             :  * requests a certificate during the handshake.
     634                 :             :  *
     635                 :             :  * Derived subclasses usually implement a certificate selector,
     636                 :             :  * although they may also choose to provide a certificate from
     637                 :             :  * elsewhere. Alternatively the user may abort this certificate
     638                 :             :  * request, which may or may not abort the TLS connection.
     639                 :             :  *
     640                 :             :  * The implementation can either be a synchronous (eg: modal dialog) or an
     641                 :             :  * asynchronous one (eg: modeless dialog). This function will take care of
     642                 :             :  * calling which ever one correctly.
     643                 :             :  *
     644                 :             :  * If the interaction is cancelled by the cancellation object, or by the
     645                 :             :  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
     646                 :             :  * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
     647                 :             :  * not support immediate cancellation.
     648                 :             :  *
     649                 :             :  * Returns: The status of the certificate request interaction.
     650                 :             :  *
     651                 :             :  * Since: 2.40
     652                 :             :  */
     653                 :             : GTlsInteractionResult
     654                 :          15 : g_tls_interaction_invoke_request_certificate (GTlsInteraction    *interaction,
     655                 :             :                                               GTlsConnection               *connection,
     656                 :             :                                               GTlsCertificateRequestFlags   flags,
     657                 :             :                                               GCancellable       *cancellable,
     658                 :             :                                               GError            **error)
     659                 :             : {
     660                 :             :   GTlsInteractionResult result;
     661                 :             :   InvokeClosure *closure;
     662                 :             :   GTlsInteractionClass *klass;
     663                 :             : 
     664                 :          15 :   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
     665                 :          15 :   g_return_val_if_fail (G_IS_TLS_CONNECTION (connection), G_TLS_INTERACTION_UNHANDLED);
     666                 :          15 :   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
     667                 :             : 
     668                 :          15 :   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
     669                 :             : 
     670                 :          15 :   if (klass->request_certificate)
     671                 :             :     {
     672                 :           6 :       closure = invoke_closure_new (interaction, G_OBJECT (connection), cancellable);
     673                 :           6 :       g_main_context_invoke (interaction->priv->context,
     674                 :             :                              on_invoke_request_certificate_sync, closure);
     675                 :           6 :       result = invoke_closure_wait_and_free (closure, error);
     676                 :             :     }
     677                 :           9 :   else if (klass->request_certificate_async)
     678                 :             :     {
     679                 :           6 :       g_return_val_if_fail (klass->request_certificate_finish, G_TLS_INTERACTION_UNHANDLED);
     680                 :             : 
     681                 :           6 :       closure = invoke_closure_new (interaction, G_OBJECT (connection), cancellable);
     682                 :           6 :       g_main_context_invoke (interaction->priv->context,
     683                 :             :                              on_invoke_request_certificate_async_as_sync, closure);
     684                 :             : 
     685                 :           6 :       result = invoke_closure_complete_and_free (interaction, closure, error);
     686                 :             :     }
     687                 :             :   else
     688                 :             :     {
     689                 :           3 :       result = G_TLS_INTERACTION_UNHANDLED;
     690                 :             :     }
     691                 :             : 
     692                 :          15 :   return result;
     693                 :             : }
     694                 :             : 
     695                 :             : /**
     696                 :             :  * g_tls_interaction_request_certificate:
     697                 :             :  * @interaction: a #GTlsInteraction object
     698                 :             :  * @connection: a #GTlsConnection object
     699                 :             :  * @flags: flags providing more information about the request
     700                 :             :  * @cancellable: an optional #GCancellable cancellation object
     701                 :             :  * @error: an optional location to place an error on failure
     702                 :             :  *
     703                 :             :  * Run synchronous interaction to ask the user to choose a certificate to use
     704                 :             :  * with the connection. In general, g_tls_interaction_invoke_request_certificate()
     705                 :             :  * should be used instead of this function.
     706                 :             :  *
     707                 :             :  * Derived subclasses usually implement a certificate selector, although they may
     708                 :             :  * also choose to provide a certificate from elsewhere. Alternatively the user may
     709                 :             :  * abort this certificate request, which will usually abort the TLS connection.
     710                 :             :  *
     711                 :             :  * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsConnection
     712                 :             :  * passed to g_tls_interaction_request_certificate() will have had its
     713                 :             :  * #GTlsConnection:certificate filled in.
     714                 :             :  *
     715                 :             :  * If the interaction is cancelled by the cancellation object, or by the
     716                 :             :  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
     717                 :             :  * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
     718                 :             :  * not support immediate cancellation.
     719                 :             :  *
     720                 :             :  * Returns: The status of the request certificate interaction.
     721                 :             :  *
     722                 :             :  * Since: 2.40
     723                 :             :  */
     724                 :             : GTlsInteractionResult
     725                 :           3 : g_tls_interaction_request_certificate (GTlsInteraction              *interaction,
     726                 :             :                                        GTlsConnection               *connection,
     727                 :             :                                        GTlsCertificateRequestFlags   flags,
     728                 :             :                                        GCancellable                 *cancellable,
     729                 :             :                                        GError                      **error)
     730                 :             : {
     731                 :             :   GTlsInteractionClass *klass;
     732                 :             : 
     733                 :           3 :   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
     734                 :           3 :   g_return_val_if_fail (G_IS_TLS_CONNECTION (connection), G_TLS_INTERACTION_UNHANDLED);
     735                 :           3 :   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
     736                 :             : 
     737                 :           3 :   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
     738                 :           3 :   if (klass->request_certificate)
     739                 :           2 :     return (klass->request_certificate) (interaction, connection, flags, cancellable, error);
     740                 :             :   else
     741                 :           1 :     return G_TLS_INTERACTION_UNHANDLED;
     742                 :             : }
     743                 :             : 
     744                 :             : /**
     745                 :             :  * g_tls_interaction_request_certificate_async:
     746                 :             :  * @interaction: a #GTlsInteraction object
     747                 :             :  * @connection: a #GTlsConnection object
     748                 :             :  * @flags: flags providing more information about the request
     749                 :             :  * @cancellable: an optional #GCancellable cancellation object
     750                 :             :  * @callback: (nullable): will be called when the interaction completes
     751                 :             :  * @user_data: (nullable): data to pass to the @callback
     752                 :             :  *
     753                 :             :  * Run asynchronous interaction to ask the user for a certificate to use with
     754                 :             :  * the connection. In general, g_tls_interaction_invoke_request_certificate() should
     755                 :             :  * be used instead of this function.
     756                 :             :  *
     757                 :             :  * Derived subclasses usually implement a certificate selector, although they may
     758                 :             :  * also choose to provide a certificate from elsewhere. @callback will be called
     759                 :             :  * when the operation completes. Alternatively the user may abort this certificate
     760                 :             :  * request, which will usually abort the TLS connection.
     761                 :             :  *
     762                 :             :  * Since: 2.40
     763                 :             :  */
     764                 :             : void
     765                 :           3 : g_tls_interaction_request_certificate_async (GTlsInteraction              *interaction,
     766                 :             :                                              GTlsConnection               *connection,
     767                 :             :                                              GTlsCertificateRequestFlags   flags,
     768                 :             :                                              GCancellable                 *cancellable,
     769                 :             :                                              GAsyncReadyCallback           callback,
     770                 :             :                                              gpointer                      user_data)
     771                 :             : {
     772                 :             :   GTlsInteractionClass *klass;
     773                 :             :   GTask *task;
     774                 :             : 
     775                 :           3 :   g_return_if_fail (G_IS_TLS_INTERACTION (interaction));
     776                 :           3 :   g_return_if_fail (G_IS_TLS_CONNECTION (connection));
     777                 :           3 :   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
     778                 :             : 
     779                 :           3 :   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
     780                 :           3 :   if (klass->request_certificate_async)
     781                 :             :     {
     782                 :           2 :       g_return_if_fail (klass->request_certificate_finish);
     783                 :           2 :       (klass->request_certificate_async) (interaction, connection, flags,
     784                 :             :                                           cancellable, callback, user_data);
     785                 :             :     }
     786                 :             :   else
     787                 :             :     {
     788                 :           1 :       task = g_task_new (interaction, cancellable, callback, user_data);
     789                 :           1 :       g_task_set_source_tag (task, g_tls_interaction_request_certificate_async);
     790                 :           1 :       g_task_return_int (task, G_TLS_INTERACTION_UNHANDLED);
     791                 :           1 :       g_object_unref (task);
     792                 :             :     }
     793                 :             : }
     794                 :             : 
     795                 :             : /**
     796                 :             :  * g_tls_interaction_request_certificate_finish:
     797                 :             :  * @interaction: a #GTlsInteraction object
     798                 :             :  * @result: the result passed to the callback
     799                 :             :  * @error: an optional location to place an error on failure
     800                 :             :  *
     801                 :             :  * Complete a request certificate user interaction request. This should be once
     802                 :             :  * the g_tls_interaction_request_certificate_async() completion callback is called.
     803                 :             :  *
     804                 :             :  * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsConnection
     805                 :             :  * passed to g_tls_interaction_request_certificate_async() will have had its
     806                 :             :  * #GTlsConnection:certificate filled in.
     807                 :             :  *
     808                 :             :  * If the interaction is cancelled by the cancellation object, or by the
     809                 :             :  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
     810                 :             :  * contains a %G_IO_ERROR_CANCELLED error code.
     811                 :             :  *
     812                 :             :  * Returns: The status of the request certificate interaction.
     813                 :             :  *
     814                 :             :  * Since: 2.40
     815                 :             :  */
     816                 :             : GTlsInteractionResult
     817                 :           3 : g_tls_interaction_request_certificate_finish (GTlsInteraction    *interaction,
     818                 :             :                                               GAsyncResult       *result,
     819                 :             :                                               GError            **error)
     820                 :             : {
     821                 :             :   GTlsInteractionClass *klass;
     822                 :             : 
     823                 :           3 :   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
     824                 :           3 :   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), G_TLS_INTERACTION_UNHANDLED);
     825                 :             : 
     826                 :           3 :   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
     827                 :           3 :   if (klass->request_certificate_finish)
     828                 :             :     {
     829                 :           2 :       g_return_val_if_fail (klass->request_certificate_async != NULL, G_TLS_INTERACTION_UNHANDLED);
     830                 :             : 
     831                 :           2 :       return (klass->request_certificate_finish) (interaction, result, error);
     832                 :             :     }
     833                 :             :   else
     834                 :             :     {
     835                 :           1 :       g_return_val_if_fail (g_async_result_is_tagged (result, g_tls_interaction_request_certificate_async), G_TLS_INTERACTION_UNHANDLED);
     836                 :             : 
     837                 :           1 :       return g_task_propagate_int (G_TASK (result), error);
     838                 :             :     }
     839                 :             : }
        

Generated by: LCOV version 2.0-1