[kdbus] KDBUS_ITEM_PAYLOAD_OFF items are (once again) relative to msg header
[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, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: Stef Walter <stefw@collabora.co.uk>
19  */
20
21 #include "config.h"
22
23 #include <string.h>
24
25 #include "gtlscertificate.h"
26 #include "gtlsconnection.h"
27 #include "gtlsinteraction.h"
28 #include "gtlspassword.h"
29 #include "gasyncresult.h"
30 #include "gcancellable.h"
31 #include "gtask.h"
32 #include "gioenumtypes.h"
33 #include "glibintl.h"
34
35
36 /**
37  * SECTION:gtlsinteraction
38  * @short_description: Interaction with the user during TLS operations.
39  * @include: gio/gio.h
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  * g_tls_connection_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  * g_tls_interaction_invoke_ask_password() to run interaction methods. These
52  * 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
63 /**
64  * GTlsInteraction:
65  *
66  * An object representing interaction that the TLS connection and database
67  * might have with the user.
68  *
69  * Since: 2.30
70  */
71
72 /**
73  * GTlsInteractionClass:
74  * @ask_password: ask for a password synchronously. If the implementation
75  *     returns %G_TLS_INTERACTION_HANDLED, then the password argument should
76  *     have been filled in by using g_tls_password_set_value() or a similar
77  *     function.
78  * @ask_password_async: ask for a password asynchronously.
79  * @ask_password_finish: complete operation to ask for a password asynchronously.
80  *     If the implementation returns %G_TLS_INTERACTION_HANDLED, then the
81  *     password argument of the async method should have been filled in by using
82  *     g_tls_password_set_value() or a similar function.
83  *
84  * The class for #GTlsInteraction. Derived classes implement the various
85  * virtual interaction methods to handle TLS interactions.
86  *
87  * Derived classes can choose to implement whichever interactions methods they'd
88  * like to support by overriding those virtual methods in their class
89  * initialization function. If a derived class implements an async method,
90  * it must also implement the corresponding finish method.
91  *
92  * The synchronous interaction methods should implement to display modal dialogs,
93  * and the asynchronous methods to display modeless dialogs.
94  *
95  * If the user cancels an interaction, then the result should be
96  * %G_TLS_INTERACTION_FAILED and the error should be set with a domain of
97  * %G_IO_ERROR and code of %G_IO_ERROR_CANCELLED.
98  *
99  * Since: 2.30
100  */
101
102 struct _GTlsInteractionPrivate {
103   GMainContext *context;
104 };
105
106 G_DEFINE_TYPE_WITH_PRIVATE (GTlsInteraction, g_tls_interaction, G_TYPE_OBJECT)
107
108 typedef struct {
109   GMutex mutex;
110
111   /* Input arguments */
112   GTlsInteraction *interaction;
113   GObject *argument;
114   GCancellable *cancellable;
115
116   /* Used when we're invoking async interactions */
117   GAsyncReadyCallback callback;
118   gpointer user_data;
119
120   /* Used when we expect results */
121   GTlsInteractionResult result;
122   GError *error;
123   gboolean complete;
124   GCond cond;
125 } InvokeClosure;
126
127 static void
128 invoke_closure_free (gpointer data)
129 {
130   InvokeClosure *closure = data;
131   g_assert (closure);
132   g_object_unref (closure->interaction);
133   g_clear_object (&closure->argument);
134   g_clear_object (&closure->cancellable);
135   g_cond_clear (&closure->cond);
136   g_mutex_clear (&closure->mutex);
137   g_clear_error (&closure->error);
138
139   /* Insurance that we've actually used these before freeing */
140   g_assert (closure->callback == NULL);
141   g_assert (closure->user_data == NULL);
142
143   g_free (closure);
144 }
145
146 static InvokeClosure *
147 invoke_closure_new (GTlsInteraction *interaction,
148                     GObject         *argument,
149                     GCancellable    *cancellable)
150 {
151   InvokeClosure *closure = g_new0 (InvokeClosure, 1);
152   closure->interaction = g_object_ref (interaction);
153   closure->argument = argument ? g_object_ref (argument) : NULL;
154   closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
155   g_mutex_init (&closure->mutex);
156   g_cond_init (&closure->cond);
157   closure->result = G_TLS_INTERACTION_UNHANDLED;
158   return closure;
159 }
160
161 static GTlsInteractionResult
162 invoke_closure_wait_and_free (InvokeClosure *closure,
163                               GError       **error)
164 {
165   GTlsInteractionResult result;
166
167   g_mutex_lock (&closure->mutex);
168
169   while (!closure->complete)
170     g_cond_wait (&closure->cond, &closure->mutex);
171
172   g_mutex_unlock (&closure->mutex);
173
174   if (closure->error)
175     {
176       g_propagate_error (error, closure->error);
177       closure->error = NULL;
178     }
179   result = closure->result;
180
181   invoke_closure_free (closure);
182   return result;
183 }
184
185 static GTlsInteractionResult
186 invoke_closure_complete_and_free (GTlsInteraction *interaction,
187                                   InvokeClosure *closure,
188                                   GError **error)
189 {
190   GTlsInteractionResult result;
191   gboolean complete;
192
193   /*
194    * Handle the case where we've been called from within the main context
195    * or in the case where the main context is not running. This approximates
196    * the behavior of a modal dialog.
197    */
198   if (g_main_context_acquire (interaction->priv->context))
199     {
200       for (;;)
201         {
202           g_mutex_lock (&closure->mutex);
203           complete = closure->complete;
204           g_mutex_unlock (&closure->mutex);
205           if (complete)
206             break;
207           g_main_context_iteration (interaction->priv->context, TRUE);
208         }
209
210       g_main_context_release (interaction->priv->context);
211
212       if (closure->error)
213         {
214           g_propagate_error (error, closure->error);
215           closure->error = NULL;
216         }
217
218       result = closure->result;
219       invoke_closure_free (closure);
220     }
221
222   /*
223    * Handle the case where we're in a different thread than the main
224    * context and a main loop is running.
225    */
226   else
227     {
228       result = invoke_closure_wait_and_free (closure, error);
229     }
230
231   return result;
232 }
233
234 static void
235 g_tls_interaction_init (GTlsInteraction *interaction)
236 {
237   interaction->priv = g_tls_interaction_get_instance_private (interaction);
238   interaction->priv->context = g_main_context_ref_thread_default ();
239 }
240
241 static void
242 g_tls_interaction_finalize (GObject *object)
243 {
244   GTlsInteraction *interaction = G_TLS_INTERACTION (object);
245
246   g_main_context_unref (interaction->priv->context);
247
248   G_OBJECT_CLASS (g_tls_interaction_parent_class)->finalize (object);
249 }
250
251 static void
252 g_tls_interaction_class_init (GTlsInteractionClass *klass)
253 {
254   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
255
256   gobject_class->finalize = g_tls_interaction_finalize;
257 }
258
259 static gboolean
260 on_invoke_ask_password_sync (gpointer user_data)
261 {
262   InvokeClosure *closure = user_data;
263   GTlsInteractionClass *klass;
264
265   g_mutex_lock (&closure->mutex);
266
267   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
268   g_assert (klass->ask_password);
269
270   closure->result = klass->ask_password (closure->interaction,
271                                          G_TLS_PASSWORD (closure->argument),
272                                          closure->cancellable,
273                                          &closure->error);
274
275   closure->complete = TRUE;
276   g_cond_signal (&closure->cond);
277   g_mutex_unlock (&closure->mutex);
278
279   return FALSE; /* don't call again */
280 }
281
282 static void
283 on_ask_password_complete (GObject      *source,
284                           GAsyncResult *result,
285                           gpointer      user_data)
286 {
287   InvokeClosure *closure = user_data;
288   GTlsInteractionClass *klass;
289
290   g_mutex_lock (&closure->mutex);
291
292   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
293   g_assert (klass->ask_password_finish);
294
295   closure->result = klass->ask_password_finish (closure->interaction,
296                                                 result,
297                                                 &closure->error);
298
299   closure->complete = TRUE;
300   g_cond_signal (&closure->cond);
301   g_mutex_unlock (&closure->mutex);
302 }
303
304 static gboolean
305 on_invoke_ask_password_async_as_sync (gpointer user_data)
306 {
307   InvokeClosure *closure = user_data;
308   GTlsInteractionClass *klass;
309
310   g_mutex_lock (&closure->mutex);
311
312   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
313   g_assert (klass->ask_password_async);
314
315   klass->ask_password_async (closure->interaction,
316                              G_TLS_PASSWORD (closure->argument),
317                              closure->cancellable,
318                              on_ask_password_complete,
319                              closure);
320
321   /* Note that we've used these */
322   closure->callback = NULL;
323   closure->user_data = NULL;
324
325   g_mutex_unlock (&closure->mutex);
326
327   return FALSE; /* don't call again */
328 }
329
330 /**
331  * g_tls_interaction_invoke_ask_password:
332  * @interaction: a #GTlsInteraction object
333  * @password: a #GTlsPassword object
334  * @cancellable: an optional #GCancellable cancellation object
335  * @error: an optional location to place an error on failure
336  *
337  * Invoke the interaction to ask the user for a password. It invokes this
338  * interaction in the main loop, specifically the #GMainContext returned by
339  * g_main_context_get_thread_default() when the interaction is created. This
340  * is called by called by #GTlsConnection or #GTlsDatabase to ask the user
341  * for a password.
342  *
343  * Derived subclasses usually implement a password prompt, although they may
344  * also choose to provide a password from elsewhere. The @password value will
345  * be filled in and then @callback will be called. Alternatively the user may
346  * abort this password request, which will usually abort the TLS connection.
347  *
348  * The implementation can either be a synchronous (eg: modal dialog) or an
349  * asynchronous one (eg: modeless dialog). This function will take care of
350  * calling which ever one correctly.
351  *
352  * If the interaction is cancelled by the cancellation object, or by the
353  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
354  * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
355  * not support immediate cancellation.
356  *
357  * Returns: The status of the ask password interaction.
358  *
359  * Since: 2.30
360  */
361 GTlsInteractionResult
362 g_tls_interaction_invoke_ask_password (GTlsInteraction    *interaction,
363                                        GTlsPassword       *password,
364                                        GCancellable       *cancellable,
365                                        GError            **error)
366 {
367   GTlsInteractionResult result;
368   InvokeClosure *closure;
369   GTlsInteractionClass *klass;
370
371   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
372   g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_INTERACTION_UNHANDLED);
373   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
374
375   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
376
377   if (klass->ask_password)
378     {
379       closure = invoke_closure_new (interaction, G_OBJECT (password), cancellable);
380       g_main_context_invoke (interaction->priv->context,
381                              on_invoke_ask_password_sync, closure);
382       result = invoke_closure_wait_and_free (closure, error);
383     }
384   else if (klass->ask_password_async)
385     {
386       g_return_val_if_fail (klass->ask_password_finish, G_TLS_INTERACTION_UNHANDLED);
387
388       closure = invoke_closure_new (interaction, G_OBJECT (password), cancellable);
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     }
398
399   return result;
400 }
401
402 /**
403  * g_tls_interaction_ask_password:
404  * @interaction: a #GTlsInteraction object
405  * @password: a #GTlsPassword object
406  * @cancellable: an optional #GCancellable cancellation object
407  * @error: an optional location to place an error on failure
408  *
409  * Run synchronous interaction to ask the user for a password. In general,
410  * g_tls_interaction_invoke_ask_password() should be used instead of this
411  * function.
412  *
413  * Derived subclasses usually implement a password prompt, although they may
414  * also choose to provide a password from elsewhere. The @password value will
415  * be filled in and then @callback will be called. Alternatively the user may
416  * abort this password request, which will usually abort the TLS connection.
417  *
418  * If the interaction is cancelled by the cancellation object, or by the
419  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
420  * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
421  * not support immediate cancellation.
422  *
423  * Returns: The status of the ask password interaction.
424  *
425  * Since: 2.30
426  */
427 GTlsInteractionResult
428 g_tls_interaction_ask_password (GTlsInteraction    *interaction,
429                                 GTlsPassword       *password,
430                                 GCancellable       *cancellable,
431                                 GError            **error)
432 {
433   GTlsInteractionClass *klass;
434
435   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
436   g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_INTERACTION_UNHANDLED);
437   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
438
439   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
440   if (klass->ask_password)
441     return (klass->ask_password) (interaction, password, cancellable, error);
442   else
443     return G_TLS_INTERACTION_UNHANDLED;
444 }
445
446 /**
447  * g_tls_interaction_ask_password_async:
448  * @interaction: a #GTlsInteraction object
449  * @password: a #GTlsPassword object
450  * @cancellable: an optional #GCancellable cancellation object
451  * @callback: (allow-none): will be called when the interaction completes
452  * @user_data: (allow-none): data to pass to the @callback
453  *
454  * Run asynchronous interaction to ask the user for a password. In general,
455  * g_tls_interaction_invoke_ask_password() should be used instead of this
456  * function.
457  *
458  * Derived subclasses usually implement a password prompt, although they may
459  * also choose to provide a password from elsewhere. The @password value will
460  * be filled in and then @callback will be called. Alternatively the user may
461  * abort this password request, which will usually abort the TLS connection.
462  *
463  * If the interaction is cancelled by the cancellation object, or by the
464  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
465  * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
466  * not support immediate cancellation.
467  *
468  * Certain implementations may not support immediate cancellation.
469  *
470  * Since: 2.30
471  */
472 void
473 g_tls_interaction_ask_password_async (GTlsInteraction    *interaction,
474                                       GTlsPassword       *password,
475                                       GCancellable       *cancellable,
476                                       GAsyncReadyCallback callback,
477                                       gpointer            user_data)
478 {
479   GTlsInteractionClass *klass;
480   GTask *task;
481
482   g_return_if_fail (G_IS_TLS_INTERACTION (interaction));
483   g_return_if_fail (G_IS_TLS_PASSWORD (password));
484   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
485
486   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
487   if (klass->ask_password_async)
488     {
489       g_return_if_fail (klass->ask_password_finish);
490       (klass->ask_password_async) (interaction, password, cancellable,
491                                    callback, user_data);
492     }
493   else
494     {
495       task = g_task_new (interaction, cancellable, callback, user_data);
496       g_task_set_source_tag (task, g_tls_interaction_ask_password_async);
497       g_task_return_int (task, G_TLS_INTERACTION_UNHANDLED);
498       g_object_unref (task);
499     }
500 }
501
502 /**
503  * g_tls_interaction_ask_password_finish:
504  * @interaction: a #GTlsInteraction object
505  * @result: the result passed to the callback
506  * @error: an optional location to place an error on failure
507  *
508  * Complete an ask password user interaction request. This should be once
509  * the g_tls_interaction_ask_password_async() completion callback is called.
510  *
511  * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsPassword passed
512  * to g_tls_interaction_ask_password() will have its password filled in.
513  *
514  * If the interaction is cancelled by the cancellation object, or by the
515  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
516  * contains a %G_IO_ERROR_CANCELLED error code.
517  *
518  * Returns: The status of the ask password interaction.
519  *
520  * Since: 2.30
521  */
522 GTlsInteractionResult
523 g_tls_interaction_ask_password_finish (GTlsInteraction    *interaction,
524                                        GAsyncResult       *result,
525                                        GError            **error)
526 {
527   GTlsInteractionClass *klass;
528
529   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
530   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), G_TLS_INTERACTION_UNHANDLED);
531
532   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
533   if (klass->ask_password_finish)
534     {
535       g_return_val_if_fail (klass->ask_password_async != NULL, G_TLS_INTERACTION_UNHANDLED);
536
537       return (klass->ask_password_finish) (interaction, result, error);
538     }
539   else
540     {
541       g_return_val_if_fail (g_async_result_is_tagged (result, g_tls_interaction_ask_password_async), G_TLS_INTERACTION_UNHANDLED);
542
543       return g_task_propagate_int (G_TASK (result), error);
544     }
545 }
546
547 static gboolean
548 on_invoke_request_certificate_sync (gpointer user_data)
549 {
550   InvokeClosure *closure = user_data;
551   GTlsInteractionClass *klass;
552
553   g_mutex_lock (&closure->mutex);
554
555   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
556   g_assert (klass->request_certificate != NULL);
557
558   closure->result = klass->request_certificate (closure->interaction,
559                                                 G_TLS_CONNECTION (closure->argument),
560                                                 0,
561                                                 closure->cancellable,
562                                                 &closure->error);
563
564   closure->complete = TRUE;
565   g_cond_signal (&closure->cond);
566   g_mutex_unlock (&closure->mutex);
567
568   return FALSE; /* don't call again */
569 }
570
571 static void
572 on_request_certificate_complete (GObject      *source,
573                                  GAsyncResult *result,
574                                  gpointer      user_data)
575 {
576   InvokeClosure *closure = user_data;
577   GTlsInteractionClass *klass;
578
579   g_mutex_lock (&closure->mutex);
580
581   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
582   g_assert (klass->request_certificate_finish != NULL);
583
584   closure->result = klass->request_certificate_finish (closure->interaction,
585                                                        result, &closure->error);
586
587   closure->complete = TRUE;
588   g_cond_signal (&closure->cond);
589   g_mutex_unlock (&closure->mutex);
590 }
591
592 static gboolean
593 on_invoke_request_certificate_async_as_sync (gpointer user_data)
594 {
595   InvokeClosure *closure = user_data;
596   GTlsInteractionClass *klass;
597
598   g_mutex_lock (&closure->mutex);
599
600   klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
601   g_assert (klass->request_certificate_async);
602
603   klass->request_certificate_async (closure->interaction,
604                                     G_TLS_CONNECTION (closure->argument), 0,
605                                     closure->cancellable,
606                                     on_request_certificate_complete,
607                                     closure);
608
609   /* Note that we've used these */
610   closure->callback = NULL;
611   closure->user_data = NULL;
612
613   g_mutex_unlock (&closure->mutex);
614
615   return FALSE; /* don't call again */
616 }
617
618 /**
619  * g_tls_interaction_invoke_request_certificate:
620  * @interaction: a #GTlsInteraction object
621  * @connection: a #GTlsConnection object
622  * @flags: flags providing more information about the request
623  * @cancellable: an optional #GCancellable cancellation object
624  * @error: an optional location to place an error on failure
625  *
626  * Invoke the interaction to ask the user to choose a certificate to
627  * use with the connection. It invokes this interaction in the main
628  * loop, specifically the #GMainContext returned by
629  * g_main_context_get_thread_default() when the interaction is
630  * created. This is called by called by #GTlsConnection when the peer
631  * requests a certificate during the handshake.
632  *
633  * Derived subclasses usually implement a certificate selector,
634  * although they may also choose to provide a certificate from
635  * elsewhere. Alternatively the user may abort this certificate
636  * request, which may or may not abort the TLS connection.
637  *
638  * The implementation can either be a synchronous (eg: modal dialog) or an
639  * asynchronous one (eg: modeless dialog). This function will take care of
640  * calling which ever one correctly.
641  *
642  * If the interaction is cancelled by the cancellation object, or by the
643  * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
644  * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
645  * not support immediate cancellation.
646  *
647  * Returns: The status of the certificate request interaction.
648  *
649  * Since: 2.40
650  */
651 GTlsInteractionResult
652 g_tls_interaction_invoke_request_certificate (GTlsInteraction    *interaction,
653                                               GTlsConnection               *connection,
654                                               GTlsCertificateRequestFlags   flags,
655                                               GCancellable       *cancellable,
656                                               GError            **error)
657 {
658   GTlsInteractionResult result;
659   InvokeClosure *closure;
660   GTlsInteractionClass *klass;
661
662   g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
663   g_return_val_if_fail (G_IS_TLS_CONNECTION (connection), G_TLS_INTERACTION_UNHANDLED);
664   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
665
666   klass = G_TLS_INTERACTION_GET_CLASS (interaction);
667
668   if (klass->request_certificate)
669     {
670       closure = invoke_closure_new (interaction, G_OBJECT (connection), cancellable);
671       g_main_context_invoke (interaction->priv->context,
672                              on_invoke_request_certificate_sync, closure);
673       result = invoke_closure_wait_and_free (closure, error);
674     }
675   else if (klass->request_certificate_async)
676     {
677       g_return_val_if_fail (klass->request_certificate_finish, G_TLS_INTERACTION_UNHANDLED);
678
679       closure = invoke_closure_new (interaction, G_OBJECT (connection), cancellable);
680       g_main_context_invoke (interaction->priv->context,
681                              on_invoke_request_certificate_async_as_sync, closure);
682
683       result = invoke_closure_complete_and_free (interaction, closure, error);
684     }
685   else
686     {
687       result = G_TLS_INTERACTION_UNHANDLED;
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 }