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, 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.
84 * The class for #GTlsInteraction. Derived classes implement the various
85 * virtual interaction methods to handle TLS interactions.
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.
92 * The synchronous interaction methods should implement to display modal dialogs,
93 * and the asynchronous methods to display modeless dialogs.
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.
102 struct _GTlsInteractionPrivate
{
103 GMainContext
*context
;
106 G_DEFINE_TYPE_WITH_PRIVATE (GTlsInteraction
, g_tls_interaction
, G_TYPE_OBJECT
)
111 /* Input arguments */
112 GTlsInteraction
*interaction
;
114 GCancellable
*cancellable
;
116 /* Used when we're invoking async interactions */
117 GAsyncReadyCallback callback
;
120 /* Used when we expect results */
121 GTlsInteractionResult result
;
128 invoke_closure_free (gpointer data
)
130 InvokeClosure
*closure
= data
;
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
);
139 /* Insurance that we've actually used these before freeing */
140 g_assert (closure
->callback
== NULL
);
141 g_assert (closure
->user_data
== NULL
);
146 static InvokeClosure
*
147 invoke_closure_new (GTlsInteraction
*interaction
,
149 GCancellable
*cancellable
)
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
;
161 static GTlsInteractionResult
162 invoke_closure_wait_and_free (InvokeClosure
*closure
,
165 GTlsInteractionResult result
;
167 g_mutex_lock (&closure
->mutex
);
169 while (!closure
->complete
)
170 g_cond_wait (&closure
->cond
, &closure
->mutex
);
172 g_mutex_unlock (&closure
->mutex
);
176 g_propagate_error (error
, closure
->error
);
177 closure
->error
= NULL
;
179 result
= closure
->result
;
181 invoke_closure_free (closure
);
185 static GTlsInteractionResult
186 invoke_closure_complete_and_free (GTlsInteraction
*interaction
,
187 InvokeClosure
*closure
,
190 GTlsInteractionResult result
;
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.
198 if (g_main_context_acquire (interaction
->priv
->context
))
202 g_mutex_lock (&closure
->mutex
);
203 complete
= closure
->complete
;
204 g_mutex_unlock (&closure
->mutex
);
207 g_main_context_iteration (interaction
->priv
->context
, TRUE
);
210 g_main_context_release (interaction
->priv
->context
);
214 g_propagate_error (error
, closure
->error
);
215 closure
->error
= NULL
;
218 result
= closure
->result
;
219 invoke_closure_free (closure
);
223 * Handle the case where we're in a different thread than the main
224 * context and a main loop is running.
228 result
= invoke_closure_wait_and_free (closure
, error
);
235 g_tls_interaction_init (GTlsInteraction
*interaction
)
237 interaction
->priv
= g_tls_interaction_get_instance_private (interaction
);
238 interaction
->priv
->context
= g_main_context_ref_thread_default ();
242 g_tls_interaction_finalize (GObject
*object
)
244 GTlsInteraction
*interaction
= G_TLS_INTERACTION (object
);
246 g_main_context_unref (interaction
->priv
->context
);
248 G_OBJECT_CLASS (g_tls_interaction_parent_class
)->finalize (object
);
252 g_tls_interaction_class_init (GTlsInteractionClass
*klass
)
254 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
256 gobject_class
->finalize
= g_tls_interaction_finalize
;
260 on_invoke_ask_password_sync (gpointer user_data
)
262 InvokeClosure
*closure
= user_data
;
263 GTlsInteractionClass
*klass
;
265 g_mutex_lock (&closure
->mutex
);
267 klass
= G_TLS_INTERACTION_GET_CLASS (closure
->interaction
);
268 g_assert (klass
->ask_password
);
270 closure
->result
= klass
->ask_password (closure
->interaction
,
271 G_TLS_PASSWORD (closure
->argument
),
272 closure
->cancellable
,
275 closure
->complete
= TRUE
;
276 g_cond_signal (&closure
->cond
);
277 g_mutex_unlock (&closure
->mutex
);
279 return FALSE
; /* don't call again */
283 on_ask_password_complete (GObject
*source
,
284 GAsyncResult
*result
,
287 InvokeClosure
*closure
= user_data
;
288 GTlsInteractionClass
*klass
;
290 g_mutex_lock (&closure
->mutex
);
292 klass
= G_TLS_INTERACTION_GET_CLASS (closure
->interaction
);
293 g_assert (klass
->ask_password_finish
);
295 closure
->result
= klass
->ask_password_finish (closure
->interaction
,
299 closure
->complete
= TRUE
;
300 g_cond_signal (&closure
->cond
);
301 g_mutex_unlock (&closure
->mutex
);
305 on_invoke_ask_password_async_as_sync (gpointer user_data
)
307 InvokeClosure
*closure
= user_data
;
308 GTlsInteractionClass
*klass
;
310 g_mutex_lock (&closure
->mutex
);
312 klass
= G_TLS_INTERACTION_GET_CLASS (closure
->interaction
);
313 g_assert (klass
->ask_password_async
);
315 klass
->ask_password_async (closure
->interaction
,
316 G_TLS_PASSWORD (closure
->argument
),
317 closure
->cancellable
,
318 on_ask_password_complete
,
321 /* Note that we've used these */
322 closure
->callback
= NULL
;
323 closure
->user_data
= NULL
;
325 g_mutex_unlock (&closure
->mutex
);
327 return FALSE
; /* don't call again */
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
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
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.
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.
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.
357 * Returns: The status of the ask password interaction.
361 GTlsInteractionResult
362 g_tls_interaction_invoke_ask_password (GTlsInteraction
*interaction
,
363 GTlsPassword
*password
,
364 GCancellable
*cancellable
,
367 GTlsInteractionResult result
;
368 InvokeClosure
*closure
;
369 GTlsInteractionClass
*klass
;
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
);
375 closure
= invoke_closure_new (interaction
, G_OBJECT (password
), cancellable
);
377 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
378 if (klass
->ask_password
)
380 g_main_context_invoke (interaction
->priv
->context
,
381 on_invoke_ask_password_sync
, closure
);
382 result
= invoke_closure_wait_and_free (closure
, error
);
384 else if (klass
->ask_password_async
)
386 g_return_val_if_fail (klass
->ask_password_finish
, G_TLS_INTERACTION_UNHANDLED
);
387 g_main_context_invoke (interaction
->priv
->context
,
388 on_invoke_ask_password_async_as_sync
, closure
);
390 result
= invoke_closure_complete_and_free (interaction
, closure
, error
);
394 result
= G_TLS_INTERACTION_UNHANDLED
;
395 invoke_closure_free (closure
);
402 * g_tls_interaction_ask_password:
403 * @interaction: a #GTlsInteraction object
404 * @password: a #GTlsPassword object
405 * @cancellable: an optional #GCancellable cancellation object
406 * @error: an optional location to place an error on failure
408 * Run synchronous interaction to ask the user for a password. In general,
409 * g_tls_interaction_invoke_ask_password() should be used instead of this
412 * Derived subclasses usually implement a password prompt, although they may
413 * also choose to provide a password from elsewhere. The @password value will
414 * be filled in and then @callback will be called. Alternatively the user may
415 * abort this password request, which will usually abort the TLS connection.
417 * If the interaction is cancelled by the cancellation object, or by the
418 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
419 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
420 * not support immediate cancellation.
422 * Returns: The status of the ask password interaction.
426 GTlsInteractionResult
427 g_tls_interaction_ask_password (GTlsInteraction
*interaction
,
428 GTlsPassword
*password
,
429 GCancellable
*cancellable
,
432 GTlsInteractionClass
*klass
;
434 g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction
), G_TLS_INTERACTION_UNHANDLED
);
435 g_return_val_if_fail (G_IS_TLS_PASSWORD (password
), G_TLS_INTERACTION_UNHANDLED
);
436 g_return_val_if_fail (cancellable
== NULL
|| G_IS_CANCELLABLE (cancellable
), G_TLS_INTERACTION_UNHANDLED
);
438 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
439 if (klass
->ask_password
)
440 return (klass
->ask_password
) (interaction
, password
, cancellable
, error
);
442 return G_TLS_INTERACTION_UNHANDLED
;
446 * g_tls_interaction_ask_password_async:
447 * @interaction: a #GTlsInteraction object
448 * @password: a #GTlsPassword object
449 * @cancellable: an optional #GCancellable cancellation object
450 * @callback: (allow-none): will be called when the interaction completes
451 * @user_data: (allow-none): data to pass to the @callback
453 * Run asynchronous interaction to ask the user for a password. In general,
454 * g_tls_interaction_invoke_ask_password() should be used instead of this
457 * Derived subclasses usually implement a password prompt, although they may
458 * also choose to provide a password from elsewhere. The @password value will
459 * be filled in and then @callback will be called. Alternatively the user may
460 * abort this password request, which will usually abort the TLS connection.
462 * If the interaction is cancelled by the cancellation object, or by the
463 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
464 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
465 * not support immediate cancellation.
467 * Certain implementations may not support immediate cancellation.
472 g_tls_interaction_ask_password_async (GTlsInteraction
*interaction
,
473 GTlsPassword
*password
,
474 GCancellable
*cancellable
,
475 GAsyncReadyCallback callback
,
478 GTlsInteractionClass
*klass
;
481 g_return_if_fail (G_IS_TLS_INTERACTION (interaction
));
482 g_return_if_fail (G_IS_TLS_PASSWORD (password
));
483 g_return_if_fail (cancellable
== NULL
|| G_IS_CANCELLABLE (cancellable
));
485 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
486 if (klass
->ask_password_async
)
488 g_return_if_fail (klass
->ask_password_finish
);
489 (klass
->ask_password_async
) (interaction
, password
, cancellable
,
490 callback
, user_data
);
494 task
= g_task_new (interaction
, cancellable
, callback
, user_data
);
495 g_task_set_source_tag (task
, g_tls_interaction_ask_password_async
);
496 g_task_return_int (task
, G_TLS_INTERACTION_UNHANDLED
);
497 g_object_unref (task
);
502 * g_tls_interaction_ask_password_finish:
503 * @interaction: a #GTlsInteraction object
504 * @result: the result passed to the callback
505 * @error: an optional location to place an error on failure
507 * Complete an ask password user interaction request. This should be once
508 * the g_tls_interaction_ask_password_async() completion callback is called.
510 * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsPassword passed
511 * to g_tls_interaction_ask_password() will have its password filled in.
513 * If the interaction is cancelled by the cancellation object, or by the
514 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
515 * contains a %G_IO_ERROR_CANCELLED error code.
517 * Returns: The status of the ask password interaction.
521 GTlsInteractionResult
522 g_tls_interaction_ask_password_finish (GTlsInteraction
*interaction
,
523 GAsyncResult
*result
,
526 GTlsInteractionClass
*klass
;
528 g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction
), G_TLS_INTERACTION_UNHANDLED
);
529 g_return_val_if_fail (G_IS_ASYNC_RESULT (result
), G_TLS_INTERACTION_UNHANDLED
);
531 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
532 if (klass
->ask_password_finish
)
534 g_return_val_if_fail (klass
->ask_password_async
!= NULL
, G_TLS_INTERACTION_UNHANDLED
);
536 return (klass
->ask_password_finish
) (interaction
, result
, error
);
540 g_return_val_if_fail (g_async_result_is_tagged (result
, g_tls_interaction_ask_password_async
), G_TLS_INTERACTION_UNHANDLED
);
542 return g_task_propagate_int (G_TASK (result
), error
);
547 on_invoke_request_certificate_sync (gpointer user_data
)
549 InvokeClosure
*closure
= user_data
;
550 GTlsInteractionClass
*klass
;
552 g_mutex_lock (&closure
->mutex
);
554 klass
= G_TLS_INTERACTION_GET_CLASS (closure
->interaction
);
555 g_assert (klass
->request_certificate
!= NULL
);
557 closure
->result
= klass
->request_certificate (closure
->interaction
,
558 G_TLS_CONNECTION (closure
->argument
),
560 closure
->cancellable
,
563 closure
->complete
= TRUE
;
564 g_cond_signal (&closure
->cond
);
565 g_mutex_unlock (&closure
->mutex
);
567 return FALSE
; /* don't call again */
571 on_request_certificate_complete (GObject
*source
,
572 GAsyncResult
*result
,
575 InvokeClosure
*closure
= user_data
;
576 GTlsInteractionClass
*klass
;
578 g_mutex_lock (&closure
->mutex
);
580 klass
= G_TLS_INTERACTION_GET_CLASS (closure
->interaction
);
581 g_assert (klass
->request_certificate_finish
!= NULL
);
583 closure
->result
= klass
->request_certificate_finish (closure
->interaction
,
584 result
, &closure
->error
);
586 closure
->complete
= TRUE
;
587 g_cond_signal (&closure
->cond
);
588 g_mutex_unlock (&closure
->mutex
);
592 on_invoke_request_certificate_async_as_sync (gpointer user_data
)
594 InvokeClosure
*closure
= user_data
;
595 GTlsInteractionClass
*klass
;
597 g_mutex_lock (&closure
->mutex
);
599 klass
= G_TLS_INTERACTION_GET_CLASS (closure
->interaction
);
600 g_assert (klass
->request_certificate_async
);
602 klass
->request_certificate_async (closure
->interaction
,
603 G_TLS_CONNECTION (closure
->argument
), 0,
604 closure
->cancellable
,
605 on_request_certificate_complete
,
608 /* Note that we've used these */
609 closure
->callback
= NULL
;
610 closure
->user_data
= NULL
;
612 g_mutex_unlock (&closure
->mutex
);
614 return FALSE
; /* don't call again */
618 * g_tls_interaction_invoke_request_certificate:
619 * @interaction: a #GTlsInteraction object
620 * @connection: a #GTlsConnection object
621 * @flags: flags providing more information about the request
622 * @cancellable: an optional #GCancellable cancellation object
623 * @error: an optional location to place an error on failure
625 * Invoke the interaction to ask the user to choose a certificate to
626 * use with the connection. It invokes this interaction in the main
627 * loop, specifically the #GMainContext returned by
628 * g_main_context_get_thread_default() when the interaction is
629 * created. This is called by called by #GTlsConnection when the peer
630 * requests a certificate during the handshake.
632 * Derived subclasses usually implement a certificate selector,
633 * although they may also choose to provide a certificate from
634 * elsewhere. Alternatively the user may abort this certificate
635 * request, which may or may not abort the TLS connection.
637 * The implementation can either be a synchronous (eg: modal dialog) or an
638 * asynchronous one (eg: modeless dialog). This function will take care of
639 * calling which ever one correctly.
641 * If the interaction is cancelled by the cancellation object, or by the
642 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
643 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
644 * not support immediate cancellation.
646 * Returns: The status of the certificate request interaction.
650 GTlsInteractionResult
651 g_tls_interaction_invoke_request_certificate (GTlsInteraction
*interaction
,
652 GTlsConnection
*connection
,
653 GTlsCertificateRequestFlags flags
,
654 GCancellable
*cancellable
,
657 GTlsInteractionResult result
;
658 InvokeClosure
*closure
;
659 GTlsInteractionClass
*klass
;
661 g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction
), G_TLS_INTERACTION_UNHANDLED
);
662 g_return_val_if_fail (G_IS_TLS_CONNECTION (connection
), G_TLS_INTERACTION_UNHANDLED
);
663 g_return_val_if_fail (cancellable
== NULL
|| G_IS_CANCELLABLE (cancellable
), G_TLS_INTERACTION_UNHANDLED
);
665 closure
= invoke_closure_new (interaction
, G_OBJECT (connection
), cancellable
);
667 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
668 if (klass
->request_certificate
)
670 g_main_context_invoke (interaction
->priv
->context
,
671 on_invoke_request_certificate_sync
, closure
);
672 result
= invoke_closure_wait_and_free (closure
, error
);
674 else if (klass
->request_certificate_async
)
676 g_return_val_if_fail (klass
->request_certificate_finish
, G_TLS_INTERACTION_UNHANDLED
);
677 g_main_context_invoke (interaction
->priv
->context
,
678 on_invoke_request_certificate_async_as_sync
, closure
);
680 result
= invoke_closure_complete_and_free (interaction
, closure
, error
);
684 result
= G_TLS_INTERACTION_UNHANDLED
;
685 invoke_closure_free (closure
);
692 * g_tls_interaction_request_certificate:
693 * @interaction: a #GTlsInteraction object
694 * @connection: a #GTlsConnection object
695 * @flags: flags providing more information about the request
696 * @cancellable: an optional #GCancellable cancellation object
697 * @error: an optional location to place an error on failure
699 * Run synchronous interaction to ask the user to choose a certificate to use
700 * with the connection. In general, g_tls_interaction_invoke_request_certificate()
701 * should be used instead of this function.
703 * Derived subclasses usually implement a certificate selector, although they may
704 * also choose to provide a certificate from elsewhere. Alternatively the user may
705 * abort this certificate request, which will usually abort the TLS connection.
707 * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsConnection
708 * passed to g_tls_interaction_request_certificate() will have had its
709 * #GTlsConnection:certificate filled in.
711 * If the interaction is cancelled by the cancellation object, or by the
712 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
713 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
714 * not support immediate cancellation.
716 * Returns: The status of the request certificate interaction.
720 GTlsInteractionResult
721 g_tls_interaction_request_certificate (GTlsInteraction
*interaction
,
722 GTlsConnection
*connection
,
723 GTlsCertificateRequestFlags flags
,
724 GCancellable
*cancellable
,
727 GTlsInteractionClass
*klass
;
729 g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction
), G_TLS_INTERACTION_UNHANDLED
);
730 g_return_val_if_fail (G_IS_TLS_CONNECTION (connection
), G_TLS_INTERACTION_UNHANDLED
);
731 g_return_val_if_fail (cancellable
== NULL
|| G_IS_CANCELLABLE (cancellable
), G_TLS_INTERACTION_UNHANDLED
);
733 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
734 if (klass
->request_certificate
)
735 return (klass
->request_certificate
) (interaction
, connection
, flags
, cancellable
, error
);
737 return G_TLS_INTERACTION_UNHANDLED
;
741 * g_tls_interaction_request_certificate_async:
742 * @interaction: a #GTlsInteraction object
743 * @connection: a #GTlsConnection object
744 * @flags: flags providing more information about the request
745 * @cancellable: an optional #GCancellable cancellation object
746 * @callback: (allow-none): will be called when the interaction completes
747 * @user_data: (allow-none): data to pass to the @callback
749 * Run asynchronous interaction to ask the user for a certificate to use with
750 * the connection. In general, g_tls_interaction_invoke_request_certificate() should
751 * be used instead of this function.
753 * Derived subclasses usually implement a certificate selector, although they may
754 * also choose to provide a certificate from elsewhere. @callback will be called
755 * when the operation completes. Alternatively the user may abort this certificate
756 * request, which will usually abort the TLS connection.
761 g_tls_interaction_request_certificate_async (GTlsInteraction
*interaction
,
762 GTlsConnection
*connection
,
763 GTlsCertificateRequestFlags flags
,
764 GCancellable
*cancellable
,
765 GAsyncReadyCallback callback
,
768 GTlsInteractionClass
*klass
;
771 g_return_if_fail (G_IS_TLS_INTERACTION (interaction
));
772 g_return_if_fail (G_IS_TLS_CONNECTION (connection
));
773 g_return_if_fail (cancellable
== NULL
|| G_IS_CANCELLABLE (cancellable
));
775 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
776 if (klass
->request_certificate_async
)
778 g_return_if_fail (klass
->request_certificate_finish
);
779 (klass
->request_certificate_async
) (interaction
, connection
, flags
,
780 cancellable
, callback
, user_data
);
784 task
= g_task_new (interaction
, cancellable
, callback
, user_data
);
785 g_task_set_source_tag (task
, g_tls_interaction_request_certificate_async
);
786 g_task_return_int (task
, G_TLS_INTERACTION_UNHANDLED
);
787 g_object_unref (task
);
792 * g_tls_interaction_request_certificate_finish:
793 * @interaction: a #GTlsInteraction object
794 * @result: the result passed to the callback
795 * @error: an optional location to place an error on failure
797 * Complete an request certificate user interaction request. This should be once
798 * the g_tls_interaction_request_certificate_async() completion callback is called.
800 * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsConnection
801 * passed to g_tls_interaction_request_certificate_async() will have had its
802 * #GTlsConnection:certificate filled in.
804 * If the interaction is cancelled by the cancellation object, or by the
805 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
806 * contains a %G_IO_ERROR_CANCELLED error code.
808 * Returns: The status of the request certificate interaction.
812 GTlsInteractionResult
813 g_tls_interaction_request_certificate_finish (GTlsInteraction
*interaction
,
814 GAsyncResult
*result
,
817 GTlsInteractionClass
*klass
;
819 g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction
), G_TLS_INTERACTION_UNHANDLED
);
820 g_return_val_if_fail (G_IS_ASYNC_RESULT (result
), G_TLS_INTERACTION_UNHANDLED
);
822 klass
= G_TLS_INTERACTION_GET_CLASS (interaction
);
823 if (klass
->request_certificate_finish
)
825 g_return_val_if_fail (klass
->request_certificate_async
!= NULL
, G_TLS_INTERACTION_UNHANDLED
);
827 return (klass
->request_certificate_finish
) (interaction
, result
, error
);
831 g_return_val_if_fail (g_async_result_is_tagged (result
, g_tls_interaction_request_certificate_async
), G_TLS_INTERACTION_UNHANDLED
);
833 return g_task_propagate_int (G_TASK (result
), error
);