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