gsettings: Fix some memory leaks on error paths
[glib.git] / gio / gtlsinteraction.c
blob85e2e5afcf29c898e6c766e7295f579033625927
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>
21 #include "config.h"
23 #include <string.h>
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"
36 /**
37 * SECTION:gtlsinteraction
38 * @short_description: Interaction with the user during TLS operations.
39 * @include: gio/gio.h
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
54 * main loop.
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.
63 /**
64 * GTlsInteraction:
66 * An object representing interaction that the TLS connection and database
67 * might have with the user.
69 * Since: 2.30
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 * @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.
108 * Since: 2.30
111 struct _GTlsInteractionPrivate {
112 GMainContext *context;
115 G_DEFINE_TYPE_WITH_PRIVATE (GTlsInteraction, g_tls_interaction, G_TYPE_OBJECT)
117 typedef struct {
118 GMutex mutex;
120 /* Input arguments */
121 GTlsInteraction *interaction;
122 GObject *argument;
123 GCancellable *cancellable;
125 /* Used when we're invoking async interactions */
126 GAsyncReadyCallback callback;
127 gpointer user_data;
129 /* Used when we expect results */
130 GTlsInteractionResult result;
131 GError *error;
132 gboolean complete;
133 GCond cond;
134 } InvokeClosure;
136 static void
137 invoke_closure_free (gpointer data)
139 InvokeClosure *closure = data;
140 g_assert (closure);
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);
152 g_free (closure);
155 static InvokeClosure *
156 invoke_closure_new (GTlsInteraction *interaction,
157 GObject *argument,
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;
167 return closure;
170 static GTlsInteractionResult
171 invoke_closure_wait_and_free (InvokeClosure *closure,
172 GError **error)
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);
183 if (closure->error)
185 g_propagate_error (error, closure->error);
186 closure->error = NULL;
188 result = closure->result;
190 invoke_closure_free (closure);
191 return result;
194 static GTlsInteractionResult
195 invoke_closure_complete_and_free (GTlsInteraction *interaction,
196 InvokeClosure *closure,
197 GError **error)
199 GTlsInteractionResult result;
200 gboolean complete;
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))
209 for (;;)
211 g_mutex_lock (&closure->mutex);
212 complete = closure->complete;
213 g_mutex_unlock (&closure->mutex);
214 if (complete)
215 break;
216 g_main_context_iteration (interaction->priv->context, TRUE);
219 g_main_context_release (interaction->priv->context);
221 if (closure->error)
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.
235 else
237 result = invoke_closure_wait_and_free (closure, error);
240 return result;
243 static void
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 ();
250 static void
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);
260 static void
261 g_tls_interaction_class_init (GTlsInteractionClass *klass)
263 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
265 gobject_class->finalize = g_tls_interaction_finalize;
268 static gboolean
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,
282 &closure->error);
284 closure->complete = TRUE;
285 g_cond_signal (&closure->cond);
286 g_mutex_unlock (&closure->mutex);
288 return FALSE; /* don't call again */
291 static void
292 on_ask_password_complete (GObject *source,
293 GAsyncResult *result,
294 gpointer user_data)
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,
305 result,
306 &closure->error);
308 closure->complete = TRUE;
309 g_cond_signal (&closure->cond);
310 g_mutex_unlock (&closure->mutex);
313 static gboolean
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,
328 closure);
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
350 * for a password.
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.
368 * Since: 2.30
370 GTlsInteractionResult
371 g_tls_interaction_invoke_ask_password (GTlsInteraction *interaction,
372 GTlsPassword *password,
373 GCancellable *cancellable,
374 GError **error)
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);
403 else
405 result = G_TLS_INTERACTION_UNHANDLED;
408 return result;
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
420 * function.
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.
434 * Since: 2.30
436 GTlsInteractionResult
437 g_tls_interaction_ask_password (GTlsInteraction *interaction,
438 GTlsPassword *password,
439 GCancellable *cancellable,
440 GError **error)
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);
451 else
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
465 * function.
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.
479 * Since: 2.30
481 void
482 g_tls_interaction_ask_password_async (GTlsInteraction *interaction,
483 GTlsPassword *password,
484 GCancellable *cancellable,
485 GAsyncReadyCallback callback,
486 gpointer user_data)
488 GTlsInteractionClass *klass;
489 GTask *task;
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);
502 else
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.
529 * Since: 2.30
531 GTlsInteractionResult
532 g_tls_interaction_ask_password_finish (GTlsInteraction *interaction,
533 GAsyncResult *result,
534 GError **error)
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);
548 else
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);
556 static gboolean
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,
571 &closure->error);
573 closure->complete = TRUE;
574 g_cond_signal (&closure->cond);
575 g_mutex_unlock (&closure->mutex);
577 return FALSE; /* don't call again */
580 static void
581 on_request_certificate_complete (GObject *source,
582 GAsyncResult *result,
583 gpointer user_data)
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);
601 static gboolean
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,
616 closure);
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.
658 * Since: 2.40
660 GTlsInteractionResult
661 g_tls_interaction_invoke_request_certificate (GTlsInteraction *interaction,
662 GTlsConnection *connection,
663 GTlsCertificateRequestFlags flags,
664 GCancellable *cancellable,
665 GError **error)
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);
694 else
696 result = G_TLS_INTERACTION_UNHANDLED;
699 return result;
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.
729 * Since: 2.40
731 GTlsInteractionResult
732 g_tls_interaction_request_certificate (GTlsInteraction *interaction,
733 GTlsConnection *connection,
734 GTlsCertificateRequestFlags flags,
735 GCancellable *cancellable,
736 GError **error)
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);
747 else
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.
769 * Since: 2.40
771 void
772 g_tls_interaction_request_certificate_async (GTlsInteraction *interaction,
773 GTlsConnection *connection,
774 GTlsCertificateRequestFlags flags,
775 GCancellable *cancellable,
776 GAsyncReadyCallback callback,
777 gpointer user_data)
779 GTlsInteractionClass *klass;
780 GTask *task;
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);
793 else
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.
821 * Since: 2.40
823 GTlsInteractionResult
824 g_tls_interaction_request_certificate_finish (GTlsInteraction *interaction,
825 GAsyncResult *result,
826 GError **error)
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);
840 else
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);