1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2011 Collabora, Ltd.
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.
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.
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.
20 * Author: Stef Walter <stefw@collabora.co.uk>
27 #include "gtlscertificate.h"
28 #include "gtlsconnection.h"
29 #include "gtlsinteraction.h"
30 #include "gtlspassword.h"
31 #include "gasyncresult.h"
32 #include "gcancellable.h"
34 #include "gioenumtypes.h"
39 * SECTION:gtlsinteraction
40 * @short_description: Interaction with the user during TLS operations.
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.
46 * To use a #GTlsInteraction with a TLS connection use
47 * g_tls_connection_set_interaction().
49 * Callers should instantiate a derived class that implements the various
50 * interaction methods to show the required dialogs.
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
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.
68 * An object representing interaction that the TLS connection and database
69 * might have with the user.
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
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.
86 * The class for #GTlsInteraction. Derived classes implement the various
87 * virtual interaction methods to handle TLS interactions.
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.
94 * The synchronous interaction methods should implement to display modal dialogs,
95 * and the asynchronous methods to display modeless dialogs.
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.
104 struct _GTlsInteractionPrivate {
105 GMainContext *context;
108 G_DEFINE_TYPE_WITH_PRIVATE (GTlsInteraction, g_tls_interaction, G_TYPE_OBJECT)
113 /* Input arguments */
114 GTlsInteraction *interaction;
116 GCancellable *cancellable;
118 /* Used when we're invoking async interactions */
119 GAsyncReadyCallback callback;
122 /* Used when we expect results */
123 GTlsInteractionResult result;
130 invoke_closure_free (gpointer data)
132 InvokeClosure *closure = data;
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);
141 /* Insurance that we've actually used these before freeing */
142 g_assert (closure->callback == NULL);
143 g_assert (closure->user_data == NULL);
148 static InvokeClosure *
149 invoke_closure_new (GTlsInteraction *interaction,
151 GCancellable *cancellable)
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;
163 static GTlsInteractionResult
164 invoke_closure_wait_and_free (InvokeClosure *closure,
167 GTlsInteractionResult result;
169 g_mutex_lock (&closure->mutex);
171 while (!closure->complete)
172 g_cond_wait (&closure->cond, &closure->mutex);
174 g_mutex_unlock (&closure->mutex);
178 g_propagate_error (error, closure->error);
179 closure->error = NULL;
181 result = closure->result;
183 invoke_closure_free (closure);
187 static GTlsInteractionResult
188 invoke_closure_complete_and_free (GTlsInteraction *interaction,
189 InvokeClosure *closure,
192 GTlsInteractionResult result;
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.
200 if (g_main_context_acquire (interaction->priv->context))
204 g_mutex_lock (&closure->mutex);
205 complete = closure->complete;
206 g_mutex_unlock (&closure->mutex);
209 g_main_context_iteration (interaction->priv->context, TRUE);
212 g_main_context_release (interaction->priv->context);
216 g_propagate_error (error, closure->error);
217 closure->error = NULL;
220 result = closure->result;
221 invoke_closure_free (closure);
225 * Handle the case where we're in a different thread than the main
226 * context and a main loop is running.
230 result = invoke_closure_wait_and_free (closure, error);
237 g_tls_interaction_init (GTlsInteraction *interaction)
239 interaction->priv = g_tls_interaction_get_instance_private (interaction);
240 interaction->priv->context = g_main_context_ref_thread_default ();
244 g_tls_interaction_finalize (GObject *object)
246 GTlsInteraction *interaction = G_TLS_INTERACTION (object);
248 g_main_context_unref (interaction->priv->context);
250 G_OBJECT_CLASS (g_tls_interaction_parent_class)->finalize (object);
254 g_tls_interaction_class_init (GTlsInteractionClass *klass)
256 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
258 gobject_class->finalize = g_tls_interaction_finalize;
262 on_invoke_ask_password_sync (gpointer user_data)
264 InvokeClosure *closure = user_data;
265 GTlsInteractionClass *klass;
267 g_mutex_lock (&closure->mutex);
269 klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
270 g_assert (klass->ask_password);
272 closure->result = klass->ask_password (closure->interaction,
273 G_TLS_PASSWORD (closure->argument),
274 closure->cancellable,
277 closure->complete = TRUE;
278 g_cond_signal (&closure->cond);
279 g_mutex_unlock (&closure->mutex);
281 return FALSE; /* don't call again */
285 on_ask_password_complete (GObject *source,
286 GAsyncResult *result,
289 InvokeClosure *closure = user_data;
290 GTlsInteractionClass *klass;
292 g_mutex_lock (&closure->mutex);
294 klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
295 g_assert (klass->ask_password_finish);
297 closure->result = klass->ask_password_finish (closure->interaction,
301 closure->complete = TRUE;
302 g_cond_signal (&closure->cond);
303 g_mutex_unlock (&closure->mutex);
307 on_invoke_ask_password_async_as_sync (gpointer user_data)
309 InvokeClosure *closure = user_data;
310 GTlsInteractionClass *klass;
312 g_mutex_lock (&closure->mutex);
314 klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
315 g_assert (klass->ask_password_async);
317 klass->ask_password_async (closure->interaction,
318 G_TLS_PASSWORD (closure->argument),
319 closure->cancellable,
320 on_ask_password_complete,
323 /* Note that we've used these */
324 closure->callback = NULL;
325 closure->user_data = NULL;
327 g_mutex_unlock (&closure->mutex);
329 return FALSE; /* don't call again */
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
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
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.
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.
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.
359 * Returns: The status of the ask password interaction.
363 GTlsInteractionResult
364 g_tls_interaction_invoke_ask_password (GTlsInteraction *interaction,
365 GTlsPassword *password,
366 GCancellable *cancellable,
369 GTlsInteractionResult result;
370 InvokeClosure *closure;
371 GTlsInteractionClass *klass;
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);
377 closure = invoke_closure_new (interaction, G_OBJECT (password), cancellable);
379 klass = G_TLS_INTERACTION_GET_CLASS (interaction);
380 if (klass->ask_password)
382 g_main_context_invoke (interaction->priv->context,
383 on_invoke_ask_password_sync, closure);
384 result = invoke_closure_wait_and_free (closure, error);
386 else if (klass->ask_password_async)
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);
392 result = invoke_closure_complete_and_free (interaction, closure, error);
396 result = G_TLS_INTERACTION_UNHANDLED;
397 invoke_closure_free (closure);
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
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
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.
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.
424 * Returns: The status of the ask password interaction.
428 GTlsInteractionResult
429 g_tls_interaction_ask_password (GTlsInteraction *interaction,
430 GTlsPassword *password,
431 GCancellable *cancellable,
434 GTlsInteractionClass *klass;
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);
440 klass = G_TLS_INTERACTION_GET_CLASS (interaction);
441 if (klass->ask_password)
442 return (klass->ask_password) (interaction, password, cancellable, error);
444 return G_TLS_INTERACTION_UNHANDLED;
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
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
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.
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.
469 * Certain implementations may not support immediate cancellation.
474 g_tls_interaction_ask_password_async (GTlsInteraction *interaction,
475 GTlsPassword *password,
476 GCancellable *cancellable,
477 GAsyncReadyCallback callback,
480 GTlsInteractionClass *klass;
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));
487 klass = G_TLS_INTERACTION_GET_CLASS (interaction);
488 if (klass->ask_password_async)
490 g_return_if_fail (klass->ask_password_finish);
491 (klass->ask_password_async) (interaction, password, cancellable,
492 callback, user_data);
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);
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
509 * Complete an ask password user interaction request. This should be once
510 * the g_tls_interaction_ask_password_async() completion callback is called.
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.
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.
519 * Returns: The status of the ask password interaction.
523 GTlsInteractionResult
524 g_tls_interaction_ask_password_finish (GTlsInteraction *interaction,
525 GAsyncResult *result,
528 GTlsInteractionClass *klass;
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);
533 klass = G_TLS_INTERACTION_GET_CLASS (interaction);
534 if (klass->ask_password_finish)
536 g_return_val_if_fail (klass->ask_password_async != NULL, G_TLS_INTERACTION_UNHANDLED);
538 return (klass->ask_password_finish) (interaction, result, error);
542 g_return_val_if_fail (g_async_result_is_tagged (result, g_tls_interaction_ask_password_async), G_TLS_INTERACTION_UNHANDLED);
544 return g_task_propagate_int (G_TASK (result), error);
549 on_invoke_request_certificate_sync (gpointer user_data)
551 InvokeClosure *closure = user_data;
552 GTlsInteractionClass *klass;
554 g_mutex_lock (&closure->mutex);
556 klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
557 g_assert (klass->request_certificate != NULL);
559 closure->result = klass->request_certificate (closure->interaction,
560 G_TLS_CONNECTION (closure->argument),
562 closure->cancellable,
565 closure->complete = TRUE;
566 g_cond_signal (&closure->cond);
567 g_mutex_unlock (&closure->mutex);
569 return FALSE; /* don't call again */
573 on_request_certificate_complete (GObject *source,
574 GAsyncResult *result,
577 InvokeClosure *closure = user_data;
578 GTlsInteractionClass *klass;
580 g_mutex_lock (&closure->mutex);
582 klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
583 g_assert (klass->request_certificate_finish != NULL);
585 closure->result = klass->request_certificate_finish (closure->interaction,
586 result, &closure->error);
588 closure->complete = TRUE;
589 g_cond_signal (&closure->cond);
590 g_mutex_unlock (&closure->mutex);
594 on_invoke_request_certificate_async_as_sync (gpointer user_data)
596 InvokeClosure *closure = user_data;
597 GTlsInteractionClass *klass;
599 g_mutex_lock (&closure->mutex);
601 klass = G_TLS_INTERACTION_GET_CLASS (closure->interaction);
602 g_assert (klass->request_certificate_async);
604 klass->request_certificate_async (closure->interaction,
605 G_TLS_CONNECTION (closure->argument), 0,
606 closure->cancellable,
607 on_request_certificate_complete,
610 /* Note that we've used these */
611 closure->callback = NULL;
612 closure->user_data = NULL;
614 g_mutex_unlock (&closure->mutex);
616 return FALSE; /* don't call again */
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
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.
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.
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.
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.
648 * Returns: The status of the certificate request interaction.
652 GTlsInteractionResult
653 g_tls_interaction_invoke_request_certificate (GTlsInteraction *interaction,
654 GTlsConnection *connection,
655 GTlsCertificateRequestFlags flags,
656 GCancellable *cancellable,
659 GTlsInteractionResult result;
660 InvokeClosure *closure;
661 GTlsInteractionClass *klass;
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);
667 closure = invoke_closure_new (interaction, G_OBJECT (connection), cancellable);
669 klass = G_TLS_INTERACTION_GET_CLASS (interaction);
670 if (klass->request_certificate)
672 g_main_context_invoke (interaction->priv->context,
673 on_invoke_request_certificate_sync, closure);
674 result = invoke_closure_wait_and_free (closure, error);
676 else if (klass->request_certificate_async)
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);
682 result = invoke_closure_complete_and_free (interaction, closure, error);
686 result = G_TLS_INTERACTION_UNHANDLED;
687 invoke_closure_free (closure);
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
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.
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.
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.
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.
718 * Returns: The status of the request certificate interaction.
722 GTlsInteractionResult
723 g_tls_interaction_request_certificate (GTlsInteraction *interaction,
724 GTlsConnection *connection,
725 GTlsCertificateRequestFlags flags,
726 GCancellable *cancellable,
729 GTlsInteractionClass *klass;
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);
735 klass = G_TLS_INTERACTION_GET_CLASS (interaction);
736 if (klass->request_certificate)
737 return (klass->request_certificate) (interaction, connection, flags, cancellable, error);
739 return G_TLS_INTERACTION_UNHANDLED;
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
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.
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.
763 g_tls_interaction_request_certificate_async (GTlsInteraction *interaction,
764 GTlsConnection *connection,
765 GTlsCertificateRequestFlags flags,
766 GCancellable *cancellable,
767 GAsyncReadyCallback callback,
770 GTlsInteractionClass *klass;
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));
777 klass = G_TLS_INTERACTION_GET_CLASS (interaction);
778 if (klass->request_certificate_async)
780 g_return_if_fail (klass->request_certificate_finish);
781 (klass->request_certificate_async) (interaction, connection, flags,
782 cancellable, callback, user_data);
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);
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
799 * Complete an request certificate user interaction request. This should be once
800 * the g_tls_interaction_request_certificate_async() completion callback is called.
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.
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.
810 * Returns: The status of the request certificate interaction.
814 GTlsInteractionResult
815 g_tls_interaction_request_certificate_finish (GTlsInteraction *interaction,
816 GAsyncResult *result,
819 GTlsInteractionClass *klass;
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);
824 klass = G_TLS_INTERACTION_GET_CLASS (interaction);
825 if (klass->request_certificate_finish)
827 g_return_val_if_fail (klass->request_certificate_async != NULL, G_TLS_INTERACTION_UNHANDLED);
829 return (klass->request_certificate_finish) (interaction, result, error);
833 g_return_val_if_fail (g_async_result_is_tagged (result, g_tls_interaction_request_certificate_async), G_TLS_INTERACTION_UNHANDLED);
835 return g_task_propagate_int (G_TASK (result), error);