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.1 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, see <http://www.gnu.org/licenses/>.
18 * Author: Stef Walter <stefw@collabora.co.uk>
25 #include "gtlscertificate.h"
26 #include "gtlsconnection.h"
27 #include "gtlsinteraction.h"
28 #include "gtlspassword.h"
29 #include "gasyncresult.h"
30 #include "gcancellable.h"
32 #include "gioenumtypes.h"
37 * SECTION:gtlsinteraction
38 * @short_description: Interaction with the user during TLS operations.
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.
44 * To use a #GTlsInteraction with a TLS connection use
45 * g_tls_connection_set_interaction().
47 * Callers should instantiate a derived class that implements the various
48 * interaction methods to show the required dialogs.
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
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.
66 * An object representing interaction that the TLS connection and database
67 * might have with the user.
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
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 * @request_certificate: ask for a certificate synchronously. If the
84 * implementation returns %G_TLS_INTERACTION_HANDLED, then the connection
85 * argument should have been filled in by using
86 * g_tls_connection_set_certificate().
87 * @request_certificate_async: ask for a certificate asynchronously.
88 * @request_certificate_finish: complete operation to ask for a certificate
89 * asynchronously. If the implementation returns %G_TLS_INTERACTION_HANDLED,
90 * then the connection argument of the async method should have been
91 * filled in by using g_tls_connection_set_certificate().
93 * The class for #GTlsInteraction. Derived classes implement the various
94 * virtual interaction methods to handle TLS interactions.
96 * Derived classes can choose to implement whichever interactions methods they'd
97 * like to support by overriding those virtual methods in their class
98 * initialization function. If a derived class implements an async method,
99 * it must also implement the corresponding finish method.
101 * The synchronous interaction methods should implement to display modal dialogs,
102 * and the asynchronous methods to display modeless dialogs.
104 * If the user cancels an interaction, then the result should be
105 * %G_TLS_INTERACTION_FAILED and the error should be set with a domain of
106 * %G_IO_ERROR and code of %G_IO_ERROR_CANCELLED.
111 struct _GTlsInteractionPrivate
{
112 GMainContext
*context
;
115 G_DEFINE_TYPE_WITH_PRIVATE (GTlsInteraction
, g_tls_interaction
, G_TYPE_OBJECT
)
120 /* Input arguments */
121 GTlsInteraction
*interaction
;
123 GCancellable
*cancellable
;
125 /* Used when we're invoking async interactions */
126 GAsyncReadyCallback callback
;
129 /* Used when we expect results */
130 GTlsInteractionResult result
;
137 invoke_closure_free (gpointer data
)
139 InvokeClosure
*closure
= data
;
141 g_object_unref (closure
->interaction
);
142 g_clear_object (&closure
->argument
);
143 g_clear_object (&closure
->cancellable
);
144 g_cond_clear (&closure
->cond
);
145 g_mutex_clear (&closure
->mutex
);
146 g_clear_error (&closure
->error
);
148 /* Insurance that we've actually used these before freeing */
149 g_assert (closure
->callback
== NULL
);
150 g_assert (closure
->user_data
== NULL
);
155 static InvokeClosure
*
156 invoke_closure_new (GTlsInteraction
*interaction
,
158 GCancellable
*cancellable
)
160 InvokeClosure
*closure
= g_new0 (InvokeClosure
, 1);
161 closure
->interaction
= g_object_ref (interaction
);
162 closure
->argument
= argument
? g_object_ref (argument
) : NULL
;
163 closure
->cancellable
= cancellable
? g_object_ref (cancellable
) : NULL
;
164 g_mutex_init (&closure
->mutex
);
165 g_cond_init (&closure
->cond
);
166 closure
->result
= G_TLS_INTERACTION_UNHANDLED
;
170 static GTlsInteractionResult
171 invoke_closure_wait_and_free (InvokeClosure
*closure
,
174 GTlsInteractionResult result
;
176 g_mutex_lock (&closure
->mutex
);
178 while (!closure
->complete
)
179 g_cond_wait (&closure
->cond
, &closure
->mutex
);
181 g_mutex_unlock (&closure
->mutex
);
185 g_propagate_error (error
, closure
->error
);
186 closure
->error
= NULL
;
188 result
= closure
->result
;
190 invoke_closure_free (closure
);
194 static GTlsInteractionResult
195 invoke_closure_complete_and_free (GTlsInteraction
*interaction
,
196 InvokeClosure
*closure
,
199 GTlsInteractionResult result
;
203 * Handle the case where we've been called from within the main context
204 * or in the case where the main context is not running. This approximates
205 * the behavior of a modal dialog.
207 if (g_main_context_acquire (interaction
->priv
->context
))
211 g_mutex_lock (&closure
->mutex
);
212 complete
= closure
->complete
;
213 g_mutex_unlock (&closure
->mutex
);
216 g_main_context_iteration (interaction
->priv
->context
, TRUE
);
219 g_main_context_release (interaction
->priv
->context
);
223 g_propagate_error (error
, closure
->error
);
224 closure
->error
= NULL
;
227 result
= closure
->result
;
228 invoke_closure_free (closure
);
232 * Handle the case where we're in a different thread than the main
233 * context and a main loop is running.
237 result
= invoke_closure_wait_and_free (closure
, error
);
244 g_tls_interaction_init (GTlsInteraction
*interaction
)
246 interaction
->priv
= g_tls_interaction_get_instance_private (interaction
);
247 interaction
->priv
->context
= g_main_context_ref_thread_default ();
251 g_tls_interaction_finalize (GObject
*object
)
253 GTlsInteraction
*interaction
= G_TLS_INTERACTION (object
);
255 g_main_context_unref (interaction
->priv
->context
);
257 G_OBJECT_CLASS (g_tls_interaction_parent_class
)->finalize (object
);
261 g_tls_interaction_class_init (GTlsInteractionClass
*klass
)
263 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
265 gobject_class
->finalize
= g_tls_interaction_finalize
;
269 on_invoke_ask_password_sync (gpointer user_data
)
271 InvokeClosure
*closure
= user_data
;
272 GTlsInteractionClass
*klass
;
274 g_mutex_lock (&closure
->mutex
);
276 klass
= G_TLS_INTERACTION_GET_CLASS (closure
->interaction
);
277 g_assert (klass
->ask_password
);
279 closure
->result
= klass
->ask_password (closure
->interaction
,
280 G_TLS_PASSWORD (closure
->argument
),
281 closure
->cancellable
,
284 closure
->complete
= TRUE
;
285 g_cond_signal (&closure
->cond
);
286 g_mutex_unlock (&closure
->mutex
);
288 return FALSE
; /* don't call again */
292 on_ask_password_complete (GObject
*source
,
293 GAsyncResult
*result
,
296 InvokeClosure
*closure
= user_data
;
297 GTlsInteractionClass
*klass
;
299 g_mutex_lock (&closure
->mutex
);
301 klass
= G_TLS_INTERACTION_GET_CLASS (closure
->interaction
);
302 g_assert (klass
->ask_password_finish
);
304 closure
->result
= klass
->ask_password_finish (closure
->interaction
,
308 closure
->complete
= TRUE
;
309 g_cond_signal (&closure
->cond
);
310 g_mutex_unlock (&closure
->mutex
);
314 on_invoke_ask_password_async_as_sync (gpointer user_data
)
316 InvokeClosure
*closure
= user_data
;
317 GTlsInteractionClass
*klass
;
319 g_mutex_lock (&closure
->mutex
);
321 klass
= G_TLS_INTERACTION_GET_CLASS (closure
->interaction
);
322 g_assert (klass
->ask_password_async
);
324 klass
->ask_password_async (closure
->interaction
,
325 G_TLS_PASSWORD (closure
->argument
),
326 closure
->cancellable
,
327 on_ask_password_complete
,
330 /* Note that we've used these */
331 closure
->callback
= NULL
;
332 closure
->user_data
= NULL
;
334 g_mutex_unlock (&closure
->mutex
);
336 return FALSE
; /* don't call again */
340 * g_tls_interaction_invoke_ask_password:
341 * @interaction: a #GTlsInteraction object
342 * @password: a #GTlsPassword object
343 * @cancellable: an optional #GCancellable cancellation object
344 * @error: an optional location to place an error on failure
346 * Invoke the interaction to ask the user for a password. It invokes this
347 * interaction in the main loop, specifically the #GMainContext returned by
348 * g_main_context_get_thread_default() when the interaction is created. This
349 * is called by called by #GTlsConnection or #GTlsDatabase to ask the user
352 * Derived subclasses usually implement a password prompt, although they may
353 * also choose to provide a password from elsewhere. The @password value will
354 * be filled in and then @callback will be called. Alternatively the user may
355 * abort this password request, which will usually abort the TLS connection.
357 * The implementation can either be a synchronous (eg: modal dialog) or an
358 * asynchronous one (eg: modeless dialog). This function will take care of
359 * calling which ever one correctly.
361 * If the interaction is cancelled by the cancellation object, or by the
362 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
363 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
364 * not support immediate cancellation.
366 * Returns: The status of the ask password interaction.
370 GTlsInteractionResult
371 g_tls_interaction_invoke_ask_password (GTlsInteraction
*interaction
,
372 GTlsPassword
*password
,
373 GCancellable
*cancellable
,
376 GTlsInteractionResult result
;
377 InvokeClosure
*closure
;
378 GTlsInteractionClass
*klass
;
380 g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction
), G_TLS_INTERACTION_UNHANDLED
);
381 g_return_val_if_fail (G_IS_TLS_PASSWORD (password
), G_TLS_INTERACTION_UNHANDLED
);
382 g_return_val_if_fail (cancellable
== NULL
|| G_IS_CANCELLABLE (cancellable
), G_TLS_INTERACTION_UNHANDLED
);
384 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
386 if (klass
->ask_password
)
388 closure
= invoke_closure_new (interaction
, G_OBJECT (password
), cancellable
);
389 g_main_context_invoke (interaction
->priv
->context
,
390 on_invoke_ask_password_sync
, closure
);
391 result
= invoke_closure_wait_and_free (closure
, error
);
393 else if (klass
->ask_password_async
)
395 g_return_val_if_fail (klass
->ask_password_finish
, G_TLS_INTERACTION_UNHANDLED
);
397 closure
= invoke_closure_new (interaction
, G_OBJECT (password
), cancellable
);
398 g_main_context_invoke (interaction
->priv
->context
,
399 on_invoke_ask_password_async_as_sync
, closure
);
401 result
= invoke_closure_complete_and_free (interaction
, closure
, error
);
405 result
= G_TLS_INTERACTION_UNHANDLED
;
412 * g_tls_interaction_ask_password:
413 * @interaction: a #GTlsInteraction object
414 * @password: a #GTlsPassword object
415 * @cancellable: an optional #GCancellable cancellation object
416 * @error: an optional location to place an error on failure
418 * Run synchronous interaction to ask the user for a password. In general,
419 * g_tls_interaction_invoke_ask_password() should be used instead of this
422 * Derived subclasses usually implement a password prompt, although they may
423 * also choose to provide a password from elsewhere. The @password value will
424 * be filled in and then @callback will be called. Alternatively the user may
425 * abort this password request, which will usually abort the TLS connection.
427 * If the interaction is cancelled by the cancellation object, or by the
428 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
429 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
430 * not support immediate cancellation.
432 * Returns: The status of the ask password interaction.
436 GTlsInteractionResult
437 g_tls_interaction_ask_password (GTlsInteraction
*interaction
,
438 GTlsPassword
*password
,
439 GCancellable
*cancellable
,
442 GTlsInteractionClass
*klass
;
444 g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction
), G_TLS_INTERACTION_UNHANDLED
);
445 g_return_val_if_fail (G_IS_TLS_PASSWORD (password
), G_TLS_INTERACTION_UNHANDLED
);
446 g_return_val_if_fail (cancellable
== NULL
|| G_IS_CANCELLABLE (cancellable
), G_TLS_INTERACTION_UNHANDLED
);
448 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
449 if (klass
->ask_password
)
450 return (klass
->ask_password
) (interaction
, password
, cancellable
, error
);
452 return G_TLS_INTERACTION_UNHANDLED
;
456 * g_tls_interaction_ask_password_async:
457 * @interaction: a #GTlsInteraction object
458 * @password: a #GTlsPassword object
459 * @cancellable: an optional #GCancellable cancellation object
460 * @callback: (nullable): will be called when the interaction completes
461 * @user_data: (nullable): data to pass to the @callback
463 * Run asynchronous interaction to ask the user for a password. In general,
464 * g_tls_interaction_invoke_ask_password() should be used instead of this
467 * Derived subclasses usually implement a password prompt, although they may
468 * also choose to provide a password from elsewhere. The @password value will
469 * be filled in and then @callback will be called. Alternatively the user may
470 * abort this password request, which will usually abort the TLS connection.
472 * If the interaction is cancelled by the cancellation object, or by the
473 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
474 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
475 * not support immediate cancellation.
477 * Certain implementations may not support immediate cancellation.
482 g_tls_interaction_ask_password_async (GTlsInteraction
*interaction
,
483 GTlsPassword
*password
,
484 GCancellable
*cancellable
,
485 GAsyncReadyCallback callback
,
488 GTlsInteractionClass
*klass
;
491 g_return_if_fail (G_IS_TLS_INTERACTION (interaction
));
492 g_return_if_fail (G_IS_TLS_PASSWORD (password
));
493 g_return_if_fail (cancellable
== NULL
|| G_IS_CANCELLABLE (cancellable
));
495 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
496 if (klass
->ask_password_async
)
498 g_return_if_fail (klass
->ask_password_finish
);
499 (klass
->ask_password_async
) (interaction
, password
, cancellable
,
500 callback
, user_data
);
504 task
= g_task_new (interaction
, cancellable
, callback
, user_data
);
505 g_task_set_source_tag (task
, g_tls_interaction_ask_password_async
);
506 g_task_return_int (task
, G_TLS_INTERACTION_UNHANDLED
);
507 g_object_unref (task
);
512 * g_tls_interaction_ask_password_finish:
513 * @interaction: a #GTlsInteraction object
514 * @result: the result passed to the callback
515 * @error: an optional location to place an error on failure
517 * Complete an ask password user interaction request. This should be once
518 * the g_tls_interaction_ask_password_async() completion callback is called.
520 * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsPassword passed
521 * to g_tls_interaction_ask_password() will have its password filled in.
523 * If the interaction is cancelled by the cancellation object, or by the
524 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
525 * contains a %G_IO_ERROR_CANCELLED error code.
527 * Returns: The status of the ask password interaction.
531 GTlsInteractionResult
532 g_tls_interaction_ask_password_finish (GTlsInteraction
*interaction
,
533 GAsyncResult
*result
,
536 GTlsInteractionClass
*klass
;
538 g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction
), G_TLS_INTERACTION_UNHANDLED
);
539 g_return_val_if_fail (G_IS_ASYNC_RESULT (result
), G_TLS_INTERACTION_UNHANDLED
);
541 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
542 if (klass
->ask_password_finish
)
544 g_return_val_if_fail (klass
->ask_password_async
!= NULL
, G_TLS_INTERACTION_UNHANDLED
);
546 return (klass
->ask_password_finish
) (interaction
, result
, error
);
550 g_return_val_if_fail (g_async_result_is_tagged (result
, g_tls_interaction_ask_password_async
), G_TLS_INTERACTION_UNHANDLED
);
552 return g_task_propagate_int (G_TASK (result
), error
);
557 on_invoke_request_certificate_sync (gpointer user_data
)
559 InvokeClosure
*closure
= user_data
;
560 GTlsInteractionClass
*klass
;
562 g_mutex_lock (&closure
->mutex
);
564 klass
= G_TLS_INTERACTION_GET_CLASS (closure
->interaction
);
565 g_assert (klass
->request_certificate
!= NULL
);
567 closure
->result
= klass
->request_certificate (closure
->interaction
,
568 G_TLS_CONNECTION (closure
->argument
),
570 closure
->cancellable
,
573 closure
->complete
= TRUE
;
574 g_cond_signal (&closure
->cond
);
575 g_mutex_unlock (&closure
->mutex
);
577 return FALSE
; /* don't call again */
581 on_request_certificate_complete (GObject
*source
,
582 GAsyncResult
*result
,
585 InvokeClosure
*closure
= user_data
;
586 GTlsInteractionClass
*klass
;
588 g_mutex_lock (&closure
->mutex
);
590 klass
= G_TLS_INTERACTION_GET_CLASS (closure
->interaction
);
591 g_assert (klass
->request_certificate_finish
!= NULL
);
593 closure
->result
= klass
->request_certificate_finish (closure
->interaction
,
594 result
, &closure
->error
);
596 closure
->complete
= TRUE
;
597 g_cond_signal (&closure
->cond
);
598 g_mutex_unlock (&closure
->mutex
);
602 on_invoke_request_certificate_async_as_sync (gpointer user_data
)
604 InvokeClosure
*closure
= user_data
;
605 GTlsInteractionClass
*klass
;
607 g_mutex_lock (&closure
->mutex
);
609 klass
= G_TLS_INTERACTION_GET_CLASS (closure
->interaction
);
610 g_assert (klass
->request_certificate_async
);
612 klass
->request_certificate_async (closure
->interaction
,
613 G_TLS_CONNECTION (closure
->argument
), 0,
614 closure
->cancellable
,
615 on_request_certificate_complete
,
618 /* Note that we've used these */
619 closure
->callback
= NULL
;
620 closure
->user_data
= NULL
;
622 g_mutex_unlock (&closure
->mutex
);
624 return FALSE
; /* don't call again */
628 * g_tls_interaction_invoke_request_certificate:
629 * @interaction: a #GTlsInteraction object
630 * @connection: a #GTlsConnection object
631 * @flags: flags providing more information about the request
632 * @cancellable: an optional #GCancellable cancellation object
633 * @error: an optional location to place an error on failure
635 * Invoke the interaction to ask the user to choose a certificate to
636 * use with the connection. It invokes this interaction in the main
637 * loop, specifically the #GMainContext returned by
638 * g_main_context_get_thread_default() when the interaction is
639 * created. This is called by called by #GTlsConnection when the peer
640 * requests a certificate during the handshake.
642 * Derived subclasses usually implement a certificate selector,
643 * although they may also choose to provide a certificate from
644 * elsewhere. Alternatively the user may abort this certificate
645 * request, which may or may not abort the TLS connection.
647 * The implementation can either be a synchronous (eg: modal dialog) or an
648 * asynchronous one (eg: modeless dialog). This function will take care of
649 * calling which ever one correctly.
651 * If the interaction is cancelled by the cancellation object, or by the
652 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
653 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
654 * not support immediate cancellation.
656 * Returns: The status of the certificate request interaction.
660 GTlsInteractionResult
661 g_tls_interaction_invoke_request_certificate (GTlsInteraction
*interaction
,
662 GTlsConnection
*connection
,
663 GTlsCertificateRequestFlags flags
,
664 GCancellable
*cancellable
,
667 GTlsInteractionResult result
;
668 InvokeClosure
*closure
;
669 GTlsInteractionClass
*klass
;
671 g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction
), G_TLS_INTERACTION_UNHANDLED
);
672 g_return_val_if_fail (G_IS_TLS_CONNECTION (connection
), G_TLS_INTERACTION_UNHANDLED
);
673 g_return_val_if_fail (cancellable
== NULL
|| G_IS_CANCELLABLE (cancellable
), G_TLS_INTERACTION_UNHANDLED
);
675 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
677 if (klass
->request_certificate
)
679 closure
= invoke_closure_new (interaction
, G_OBJECT (connection
), cancellable
);
680 g_main_context_invoke (interaction
->priv
->context
,
681 on_invoke_request_certificate_sync
, closure
);
682 result
= invoke_closure_wait_and_free (closure
, error
);
684 else if (klass
->request_certificate_async
)
686 g_return_val_if_fail (klass
->request_certificate_finish
, G_TLS_INTERACTION_UNHANDLED
);
688 closure
= invoke_closure_new (interaction
, G_OBJECT (connection
), cancellable
);
689 g_main_context_invoke (interaction
->priv
->context
,
690 on_invoke_request_certificate_async_as_sync
, closure
);
692 result
= invoke_closure_complete_and_free (interaction
, closure
, error
);
696 result
= G_TLS_INTERACTION_UNHANDLED
;
703 * g_tls_interaction_request_certificate:
704 * @interaction: a #GTlsInteraction object
705 * @connection: a #GTlsConnection object
706 * @flags: flags providing more information about the request
707 * @cancellable: an optional #GCancellable cancellation object
708 * @error: an optional location to place an error on failure
710 * Run synchronous interaction to ask the user to choose a certificate to use
711 * with the connection. In general, g_tls_interaction_invoke_request_certificate()
712 * should be used instead of this function.
714 * Derived subclasses usually implement a certificate selector, although they may
715 * also choose to provide a certificate from elsewhere. Alternatively the user may
716 * abort this certificate request, which will usually abort the TLS connection.
718 * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsConnection
719 * passed to g_tls_interaction_request_certificate() will have had its
720 * #GTlsConnection:certificate filled in.
722 * If the interaction is cancelled by the cancellation object, or by the
723 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
724 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
725 * not support immediate cancellation.
727 * Returns: The status of the request certificate interaction.
731 GTlsInteractionResult
732 g_tls_interaction_request_certificate (GTlsInteraction
*interaction
,
733 GTlsConnection
*connection
,
734 GTlsCertificateRequestFlags flags
,
735 GCancellable
*cancellable
,
738 GTlsInteractionClass
*klass
;
740 g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction
), G_TLS_INTERACTION_UNHANDLED
);
741 g_return_val_if_fail (G_IS_TLS_CONNECTION (connection
), G_TLS_INTERACTION_UNHANDLED
);
742 g_return_val_if_fail (cancellable
== NULL
|| G_IS_CANCELLABLE (cancellable
), G_TLS_INTERACTION_UNHANDLED
);
744 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
745 if (klass
->request_certificate
)
746 return (klass
->request_certificate
) (interaction
, connection
, flags
, cancellable
, error
);
748 return G_TLS_INTERACTION_UNHANDLED
;
752 * g_tls_interaction_request_certificate_async:
753 * @interaction: a #GTlsInteraction object
754 * @connection: a #GTlsConnection object
755 * @flags: flags providing more information about the request
756 * @cancellable: an optional #GCancellable cancellation object
757 * @callback: (nullable): will be called when the interaction completes
758 * @user_data: (nullable): data to pass to the @callback
760 * Run asynchronous interaction to ask the user for a certificate to use with
761 * the connection. In general, g_tls_interaction_invoke_request_certificate() should
762 * be used instead of this function.
764 * Derived subclasses usually implement a certificate selector, although they may
765 * also choose to provide a certificate from elsewhere. @callback will be called
766 * when the operation completes. Alternatively the user may abort this certificate
767 * request, which will usually abort the TLS connection.
772 g_tls_interaction_request_certificate_async (GTlsInteraction
*interaction
,
773 GTlsConnection
*connection
,
774 GTlsCertificateRequestFlags flags
,
775 GCancellable
*cancellable
,
776 GAsyncReadyCallback callback
,
779 GTlsInteractionClass
*klass
;
782 g_return_if_fail (G_IS_TLS_INTERACTION (interaction
));
783 g_return_if_fail (G_IS_TLS_CONNECTION (connection
));
784 g_return_if_fail (cancellable
== NULL
|| G_IS_CANCELLABLE (cancellable
));
786 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
787 if (klass
->request_certificate_async
)
789 g_return_if_fail (klass
->request_certificate_finish
);
790 (klass
->request_certificate_async
) (interaction
, connection
, flags
,
791 cancellable
, callback
, user_data
);
795 task
= g_task_new (interaction
, cancellable
, callback
, user_data
);
796 g_task_set_source_tag (task
, g_tls_interaction_request_certificate_async
);
797 g_task_return_int (task
, G_TLS_INTERACTION_UNHANDLED
);
798 g_object_unref (task
);
803 * g_tls_interaction_request_certificate_finish:
804 * @interaction: a #GTlsInteraction object
805 * @result: the result passed to the callback
806 * @error: an optional location to place an error on failure
808 * Complete an request certificate user interaction request. This should be once
809 * the g_tls_interaction_request_certificate_async() completion callback is called.
811 * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsConnection
812 * passed to g_tls_interaction_request_certificate_async() will have had its
813 * #GTlsConnection:certificate filled in.
815 * If the interaction is cancelled by the cancellation object, or by the
816 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
817 * contains a %G_IO_ERROR_CANCELLED error code.
819 * Returns: The status of the request certificate interaction.
823 GTlsInteractionResult
824 g_tls_interaction_request_certificate_finish (GTlsInteraction
*interaction
,
825 GAsyncResult
*result
,
828 GTlsInteractionClass
*klass
;
830 g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction
), G_TLS_INTERACTION_UNHANDLED
);
831 g_return_val_if_fail (G_IS_ASYNC_RESULT (result
), G_TLS_INTERACTION_UNHANDLED
);
833 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
834 if (klass
->request_certificate_finish
)
836 g_return_val_if_fail (klass
->request_certificate_async
!= NULL
, G_TLS_INTERACTION_UNHANDLED
);
838 return (klass
->request_certificate_finish
) (interaction
, result
, error
);
842 g_return_val_if_fail (g_async_result_is_tagged (result
, g_tls_interaction_request_certificate_async
), G_TLS_INTERACTION_UNHANDLED
);
844 return g_task_propagate_int (G_TASK (result
), error
);