Add a request_certificate virtual method to GTlsInteraction
[platform/upstream/glib.git] / gio / gtlsinteraction.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright (C) 2011 Collabora, Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
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  *
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 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 invoke_closure_free (gpointer data)
131 {
132   InvokeClosure *closure = data;
133   g_assert (closure);
134   g_object_unref (closure->interaction);
135   g_clear_object (&closure->argument);
136   g_clear_object (&closure->cancellable);
137   g_cond_clear (&closure->cond);
138   g_mutex_clear (&closure->mutex);
139   g_clear_error (&closure->error);
140
141   /* Insurance that we've actually used these before freeing */
142   g_assert (closure->callback == NULL);
143   g_assert (closure->user_data == NULL);
144
145   g_free (closure);
146 }
147
148 static InvokeClosure *
149 invoke_closure_new (GTlsInteraction *interaction,
150                     GObject         *argument,
151                     GCancellable    *cancellable)
152 {
153   InvokeClosure *closure = g_new0 (InvokeClosure, 1);
154   closure->interaction = g_object_ref (interaction);
155   closure->argument = argument ? g_object_ref (argument) : NULL;
156   closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
157   g_mutex_init (&closure->mutex);
158   g_cond_init (&closure->cond);
159   closure->result = G_TLS_INTERACTION_UNHANDLED;
160   return closure;
161 }
162
163 static GTlsInteractionResult
164 invoke_closure_wait_and_free (InvokeClosure *closure,
165                               GError       **error)
166 {
167   GTlsInteractionResult result;
168
169   g_mutex_lock (&closure->mutex);
170
171   while (!closure->complete)
172     g_cond_wait (&closure->cond, &closure->mutex);
173
174   g_mutex_unlock (&closure->mutex);
175
176   if (closure->error)
177     {
178       g_propagate_error (error, closure->error);
179       closure->error = NULL;
180     }
181   result = closure->result;
182
183   invoke_closure_free (closure);
184   return result;
185 }
186
187 static GTlsInteractionResult
188 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   if (g_main_context_acquire (interaction->priv->context))
201     {
202       for (;;)
203         {
204           g_mutex_lock (&closure->mutex);
205           complete = closure->complete;
206           g_mutex_unlock (&closure->mutex);
207           if (complete)
208             break;
209           g_main_context_iteration (interaction->priv->context, TRUE);
210         }
211
212       g_main_context_release (interaction->priv->context);
213
214       if (closure->error)
215         {
216           g_propagate_error (error, closure->error);
217           closure->error = NULL;
218         }
219
220       result = closure->result;
221       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       result = invoke_closure_wait_and_free (closure, error);
231     }
232
233   return result;
234 }
235
236 static void
237 g_tls_interaction_init (GTlsInteraction *interaction)
238 {
239   interaction->priv = g_tls_interaction_get_instance_private (interaction);
240   interaction->priv->context = g_main_context_ref_thread_default ();
241 }
242
243 static void
244 g_tls_interaction_finalize (GObject *object)
245 {
246   GTlsInteraction *interaction = G_TLS_INTERACTION (object);
247
248   g_main_context_unref (interaction->priv->context);
249
250   G_OBJECT_CLASS (g_tls_interaction_parent_class)->finalize (object);
251 }
252
253 static void
254 g_tls_interaction_class_init (GTlsInteractionClass *klass)
255 {
256   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
257
258   gobject_class->finalize = g_tls_interaction_finalize;
259 }
260
261 static gboolean
262 on_invoke_ask_password_sync (gpointer user_data)
263 {
264   InvokeClosure *closure = user_data;
265   GTlsInteractionClass *klass;
266
267   g_mutex_lock (&closure->mutex);
268
269   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
270   g_assert (klass->ask_password);
271
272   closure->result = klass->ask_password (closure->interaction,
273                                          G_TLS_PASSWORD (closure->argument),
274                                          closure->cancellable,
275                                          &closure->error);
276
277   closure->complete = TRUE;
278   g_cond_signal (&closure->cond);
279   g_mutex_unlock (&closure->mutex);
280
281   return FALSE; /* don't call again */
282 }
283
284 static void
285 on_ask_password_complete (GObject      *source,
286                           GAsyncResult *result,
287                           gpointer      user_data)
288 {
289   InvokeClosure *closure = user_data;
290   GTlsInteractionClass *klass;
291
292   g_mutex_lock (&closure->mutex);
293
294   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
295   g_assert (klass->ask_password_finish);
296
297   closure->result = klass->ask_password_finish (closure->interaction,
298                                                 result,
299                                                 &closure->error);
300
301   closure->complete = TRUE;
302   g_cond_signal (&closure->cond);
303   g_mutex_unlock (&closure->mutex);
304 }
305
306 static gboolean
307 on_invoke_ask_password_async_as_sync (gpointer user_data)
308 {
309   InvokeClosure *closure = user_data;
310   GTlsInteractionClass *klass;
311
312   g_mutex_lock (&closure->mutex);
313
314   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
315   g_assert (klass->ask_password_async);
316
317   klass->ask_password_async (closure->interaction,
318                              G_TLS_PASSWORD (closure->argument),
319                              closure->cancellable,
320                              on_ask_password_complete,
321                              closure);
322
323   /* Note that we've used these */
324   closure->callback = NULL;
325   closure->user_data = NULL;
326
327   g_mutex_unlock (&closure->mutex);
328
329   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 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   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
374   g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_INTERACTION_UNHANDLED);
375   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
376
377   closure = invoke_closure_new (interaction, G_OBJECT (password), cancellable);
378
379   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
380   if (klass->ask_password)
381     {
382       g_main_context_invoke (interaction->priv->context,
383                              on_invoke_ask_password_sync, closure);
384       result = invoke_closure_wait_and_free (closure, error);
385     }
386   else if (klass->ask_password_async)
387     {
388       g_return_val_if_fail (klass->ask_password_finish, G_TLS_INTERACTION_UNHANDLED);
389       g_main_context_invoke (interaction->priv->context,
390                              on_invoke_ask_password_async_as_sync, closure);
391
392       result = invoke_closure_complete_and_free (interaction, closure, error);
393     }
394   else
395     {
396       result = G_TLS_INTERACTION_UNHANDLED;
397       invoke_closure_free (closure);
398     }
399
400   return result;
401 }
402
403 /**
404  * g_tls_interaction_ask_password:
405  * @interaction: a #GTlsInteraction object
406  * @password: a #GTlsPassword object
407  * @cancellable: an optional #GCancellable cancellation object
408  * @error: an optional location to place an error on failure
409  *
410  * Run synchronous interaction to ask the user for a password. In general,
411  * g_tls_interaction_invoke_ask_password() should be used instead of this
412  * function.
413  *
414  * Derived subclasses usually implement a password prompt, although they may
415  * also choose to provide a password from elsewhere. The @password value will
416  * be filled in and then @callback will be called. Alternatively the user may
417  * abort this password request, which will usually abort the TLS connection.
418  *
419  * If the interaction is cancelled by the cancellation object, or by the
420  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
421  * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
422  * not support immediate cancellation.
423  *
424  * Returns: The status of the ask password interaction.
425  *
426  * Since: 2.30
427  */
428 GTlsInteractionResult
429 g_tls_interaction_ask_password (GTlsInteraction    *interaction,
430                                 GTlsPassword       *password,
431                                 GCancellable       *cancellable,
432                                 GError            **error)
433 {
434   GTlsInteractionClass *klass;
435
436   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
437   g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_INTERACTION_UNHANDLED);
438   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
439
440   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
441   if (klass->ask_password)
442     return (klass->ask_password) (interaction, password, cancellable, error);
443   else
444     return G_TLS_INTERACTION_UNHANDLED;
445 }
446
447 /**
448  * g_tls_interaction_ask_password_async:
449  * @interaction: a #GTlsInteraction object
450  * @password: a #GTlsPassword object
451  * @cancellable: an optional #GCancellable cancellation object
452  * @callback: (allow-none): will be called when the interaction completes
453  * @user_data: (allow-none): data to pass to the @callback
454  *
455  * Run asynchronous interaction to ask the user for a password. In general,
456  * g_tls_interaction_invoke_ask_password() should be used instead of this
457  * function.
458  *
459  * Derived subclasses usually implement a password prompt, although they may
460  * also choose to provide a password from elsewhere. The @password value will
461  * be filled in and then @callback will be called. Alternatively the user may
462  * abort this password request, which will usually abort the TLS connection.
463  *
464  * If the interaction is cancelled by the cancellation object, or by the
465  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
466  * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
467  * not support immediate cancellation.
468  *
469  * Certain implementations may not support immediate cancellation.
470  *
471  * Since: 2.30
472  */
473 void
474 g_tls_interaction_ask_password_async (GTlsInteraction    *interaction,
475                                       GTlsPassword       *password,
476                                       GCancellable       *cancellable,
477                                       GAsyncReadyCallback callback,
478                                       gpointer            user_data)
479 {
480   GTlsInteractionClass *klass;
481   GTask *task;
482
483   g_return_if_fail (G_IS_TLS_INTERACTION (interaction));
484   g_return_if_fail (G_IS_TLS_PASSWORD (password));
485   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
486
487   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
488   if (klass->ask_password_async)
489     {
490       g_return_if_fail (klass->ask_password_finish);
491       (klass->ask_password_async) (interaction, password, cancellable,
492                                    callback, user_data);
493     }
494   else
495     {
496       task = g_task_new (interaction, cancellable, callback, user_data);
497       g_task_set_source_tag (task, g_tls_interaction_ask_password_async);
498       g_task_return_int (task, G_TLS_INTERACTION_UNHANDLED);
499       g_object_unref (task);
500     }
501 }
502
503 /**
504  * g_tls_interaction_ask_password_finish:
505  * @interaction: a #GTlsInteraction object
506  * @result: the result passed to the callback
507  * @error: an optional location to place an error on failure
508  *
509  * Complete an ask password user interaction request. This should be once
510  * the g_tls_interaction_ask_password_async() completion callback is called.
511  *
512  * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsPassword passed
513  * to g_tls_interaction_ask_password() will have its password filled in.
514  *
515  * If the interaction is cancelled by the cancellation object, or by the
516  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
517  * contains a %G_IO_ERROR_CANCELLED error code.
518  *
519  * Returns: The status of the ask password interaction.
520  *
521  * Since: 2.30
522  */
523 GTlsInteractionResult
524 g_tls_interaction_ask_password_finish (GTlsInteraction    *interaction,
525                                        GAsyncResult       *result,
526                                        GError            **error)
527 {
528   GTlsInteractionClass *klass;
529
530   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
531   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), G_TLS_INTERACTION_UNHANDLED);
532
533   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
534   if (klass->ask_password_finish)
535     {
536       g_return_val_if_fail (klass->ask_password_async != NULL, G_TLS_INTERACTION_UNHANDLED);
537
538       return (klass->ask_password_finish) (interaction, result, error);
539     }
540   else
541     {
542       g_return_val_if_fail (g_async_result_is_tagged (result, g_tls_interaction_ask_password_async), G_TLS_INTERACTION_UNHANDLED);
543
544       return g_task_propagate_int (G_TASK (result), error);
545     }
546 }
547
548 static gboolean
549 on_invoke_request_certificate_sync (gpointer user_data)
550 {
551   InvokeClosure *closure = user_data;
552   GTlsInteractionClass *klass;
553
554   g_mutex_lock (&closure->mutex);
555
556   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
557   g_assert (klass->request_certificate != NULL);
558
559   closure->result = klass->request_certificate (closure->interaction,
560                                                 G_TLS_CONNECTION (closure->argument),
561                                                 0,
562                                                 closure->cancellable,
563                                                 &closure->error);
564
565   closure->complete = TRUE;
566   g_cond_signal (&closure->cond);
567   g_mutex_unlock (&closure->mutex);
568
569   return FALSE; /* don't call again */
570 }
571
572 static void
573 on_request_certificate_complete (GObject      *source,
574                                  GAsyncResult *result,
575                                  gpointer      user_data)
576 {
577   InvokeClosure *closure = user_data;
578   GTlsInteractionClass *klass;
579
580   g_mutex_lock (&closure->mutex);
581
582   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
583   g_assert (klass->request_certificate_finish != NULL);
584
585   closure->result = klass->request_certificate_finish (closure->interaction,
586                                                        result, &closure->error);
587
588   closure->complete = TRUE;
589   g_cond_signal (&closure->cond);
590   g_mutex_unlock (&closure->mutex);
591 }
592
593 static gboolean
594 on_invoke_request_certificate_async_as_sync (gpointer user_data)
595 {
596   InvokeClosure *closure = user_data;
597   GTlsInteractionClass *klass;
598
599   g_mutex_lock (&closure->mutex);
600
601   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
602   g_assert (klass->request_certificate_async);
603
604   klass->request_certificate_async (closure->interaction,
605                                     G_TLS_CONNECTION (closure->argument), 0,
606                                     closure->cancellable,
607                                     on_request_certificate_complete,
608                                     closure);
609
610   /* Note that we've used these */
611   closure->callback = NULL;
612   closure->user_data = NULL;
613
614   g_mutex_unlock (&closure->mutex);
615
616   return FALSE; /* don't call again */
617 }
618
619 /**
620  * g_tls_interaction_invoke_request_certificate:
621  * @interaction: a #GTlsInteraction object
622  * @connection: a #GTlsConnection object
623  * @flags: flags providing more information about the request
624  * @cancellable: an optional #GCancellable cancellation object
625  * @error: an optional location to place an error on failure
626  *
627  * Invoke the interaction to ask the user to choose a certificate to
628  * use with the connection. It invokes this interaction in the main
629  * loop, specifically the #GMainContext returned by
630  * g_main_context_get_thread_default() when the interaction is
631  * created. This is called by called by #GTlsConnection when the peer
632  * requests a certificate during the handshake.
633  *
634  * Derived subclasses usually implement a certificate selector,
635  * although they may also choose to provide a certificate from
636  * elsewhere. Alternatively the user may abort this certificate
637  * request, which may or may not abort the TLS connection.
638  *
639  * The implementation can either be a synchronous (eg: modal dialog) or an
640  * asynchronous one (eg: modeless dialog). This function will take care of
641  * calling which ever one correctly.
642  *
643  * If the interaction is cancelled by the cancellation object, or by the
644  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
645  * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
646  * not support immediate cancellation.
647  *
648  * Returns: The status of the certificate request interaction.
649  *
650  * Since: 2.40
651  */
652 GTlsInteractionResult
653 g_tls_interaction_invoke_request_certificate (GTlsInteraction    *interaction,
654                                               GTlsConnection               *connection,
655                                               GTlsCertificateRequestFlags   flags,
656                                               GCancellable       *cancellable,
657                                               GError            **error)
658 {
659   GTlsInteractionResult result;
660   InvokeClosure *closure;
661   GTlsInteractionClass *klass;
662
663   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
664   g_return_val_if_fail (G_IS_TLS_CONNECTION (connection), G_TLS_INTERACTION_UNHANDLED);
665   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
666
667   closure = invoke_closure_new (interaction, G_OBJECT (connection), cancellable);
668
669   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
670   if (klass->request_certificate)
671     {
672       g_main_context_invoke (interaction->priv->context,
673                              on_invoke_request_certificate_sync, closure);
674       result = invoke_closure_wait_and_free (closure, error);
675     }
676   else if (klass->request_certificate_async)
677     {
678       g_return_val_if_fail (klass->request_certificate_finish, G_TLS_INTERACTION_UNHANDLED);
679       g_main_context_invoke (interaction->priv->context,
680                              on_invoke_request_certificate_async_as_sync, closure);
681
682       result = invoke_closure_complete_and_free (interaction, closure, error);
683     }
684   else
685     {
686       result = G_TLS_INTERACTION_UNHANDLED;
687       invoke_closure_free (closure);
688     }
689
690   return result;
691 }
692
693 /**
694  * g_tls_interaction_request_certificate:
695  * @interaction: a #GTlsInteraction object
696  * @connection: a #GTlsConnection object
697  * @flags: flags providing more information about the request
698  * @cancellable: an optional #GCancellable cancellation object
699  * @error: an optional location to place an error on failure
700  *
701  * Run synchronous interaction to ask the user to choose a certificate to use
702  * with the connection. In general, g_tls_interaction_invoke_request_certificate()
703  * should be used instead of this function.
704  *
705  * Derived subclasses usually implement a certificate selector, although they may
706  * also choose to provide a certificate from elsewhere. Alternatively the user may
707  * abort this certificate request, which will usually abort the TLS connection.
708  *
709  * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsConnection
710  * passed to g_tls_interaction_request_certificate() will have had its
711  * #GTlsConnection:certificate filled in.
712  *
713  * If the interaction is cancelled by the cancellation object, or by the
714  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
715  * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
716  * not support immediate cancellation.
717  *
718  * Returns: The status of the request certificate interaction.
719  *
720  * Since: 2.40
721  */
722 GTlsInteractionResult
723 g_tls_interaction_request_certificate (GTlsInteraction              *interaction,
724                                        GTlsConnection               *connection,
725                                        GTlsCertificateRequestFlags   flags,
726                                        GCancellable                 *cancellable,
727                                        GError                      **error)
728 {
729   GTlsInteractionClass *klass;
730
731   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
732   g_return_val_if_fail (G_IS_TLS_CONNECTION (connection), G_TLS_INTERACTION_UNHANDLED);
733   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
734
735   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
736   if (klass->request_certificate)
737     return (klass->request_certificate) (interaction, connection, flags, cancellable, error);
738   else
739     return G_TLS_INTERACTION_UNHANDLED;
740 }
741
742 /**
743  * g_tls_interaction_request_certificate_async:
744  * @interaction: a #GTlsInteraction object
745  * @connection: a #GTlsConnection object
746  * @flags: flags providing more information about the request
747  * @cancellable: an optional #GCancellable cancellation object
748  * @callback: (allow-none): will be called when the interaction completes
749  * @user_data: (allow-none): data to pass to the @callback
750  *
751  * Run asynchronous interaction to ask the user for a certificate to use with
752  * the connection. In general, g_tls_interaction_invoke_request_certificate() should
753  * be used instead of this function.
754  *
755  * Derived subclasses usually implement a certificate selector, although they may
756  * also choose to provide a certificate from elsewhere. @callback will be called
757  * when the operation completes. Alternatively the user may abort this certificate
758  * request, which will usually abort the TLS connection.
759  *
760  * Since: 2.40
761  */
762 void
763 g_tls_interaction_request_certificate_async (GTlsInteraction              *interaction,
764                                              GTlsConnection               *connection,
765                                              GTlsCertificateRequestFlags   flags,
766                                              GCancellable                 *cancellable,
767                                              GAsyncReadyCallback           callback,
768                                              gpointer                      user_data)
769 {
770   GTlsInteractionClass *klass;
771   GTask *task;
772
773   g_return_if_fail (G_IS_TLS_INTERACTION (interaction));
774   g_return_if_fail (G_IS_TLS_CONNECTION (connection));
775   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
776
777   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
778   if (klass->request_certificate_async)
779     {
780       g_return_if_fail (klass->request_certificate_finish);
781       (klass->request_certificate_async) (interaction, connection, flags,
782                                           cancellable, callback, user_data);
783     }
784   else
785     {
786       task = g_task_new (interaction, cancellable, callback, user_data);
787       g_task_set_source_tag (task, g_tls_interaction_request_certificate_async);
788       g_task_return_int (task, G_TLS_INTERACTION_UNHANDLED);
789       g_object_unref (task);
790     }
791 }
792
793 /**
794  * g_tls_interaction_request_certificate_finish:
795  * @interaction: a #GTlsInteraction object
796  * @result: the result passed to the callback
797  * @error: an optional location to place an error on failure
798  *
799  * Complete an request certificate user interaction request. This should be once
800  * the g_tls_interaction_request_certificate_async() completion callback is called.
801  *
802  * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsConnection
803  * passed to g_tls_interaction_request_certificate_async() will have had its
804  * #GTlsConnection:certificate filled in.
805  *
806  * If the interaction is cancelled by the cancellation object, or by the
807  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
808  * contains a %G_IO_ERROR_CANCELLED error code.
809  *
810  * Returns: The status of the request certificate interaction.
811  *
812  * Since: 2.40
813  */
814 GTlsInteractionResult
815 g_tls_interaction_request_certificate_finish (GTlsInteraction    *interaction,
816                                               GAsyncResult       *result,
817                                               GError            **error)
818 {
819   GTlsInteractionClass *klass;
820
821   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
822   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), G_TLS_INTERACTION_UNHANDLED);
823
824   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
825   if (klass->request_certificate_finish)
826     {
827       g_return_val_if_fail (klass->request_certificate_async != NULL, G_TLS_INTERACTION_UNHANDLED);
828
829       return (klass->request_certificate_finish) (interaction, result, error);
830     }
831   else
832     {
833       g_return_val_if_fail (g_async_result_is_tagged (result, g_tls_interaction_request_certificate_async), G_TLS_INTERACTION_UNHANDLED);
834
835       return g_task_propagate_int (G_TASK (result), error);
836     }
837 }