Пример #1
0
/**
 * g_tls_interaction_ask_password_finish:
 * @interaction: a #GTlsInteraction object
 * @result: the result passed to the callback
 * @error: an optional location to place an error on failure
 *
 * Complete an ask password user interaction request. This should be once
 * the g_tls_interaction_ask_password_async() completion callback is called.
 *
 * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsPassword passed
 * to g_tls_interaction_ask_password() will have its password filled in.
 *
 * If the interaction is cancelled by the cancellation object, or by the
 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
 * contains a %G_IO_ERROR_CANCELLED error code.
 *
 * Returns: The status of the ask password interaction.
 *
 * Since: 2.30
 */
GTlsInteractionResult
g_tls_interaction_ask_password_finish (GTlsInteraction    *interaction,
                                       GAsyncResult       *result,
                                       GError            **error)
{
  GTlsInteractionClass *klass;

  g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), G_TLS_INTERACTION_UNHANDLED);

  /* If it's one of our simple unhandled async results, handle here */
  if (g_simple_async_result_is_valid (result, G_OBJECT (interaction),
                                      g_tls_interaction_ask_password_async))
    {
      return G_TLS_INTERACTION_UNHANDLED;
    }

  /* Invoke finish of derived class */
  else
    {
      klass = G_TLS_INTERACTION_GET_CLASS (interaction);
      g_return_val_if_fail (klass->ask_password_finish, G_TLS_INTERACTION_UNHANDLED);
      return (klass->ask_password_finish) (interaction, result, error);
    }
}
Пример #2
0
/**
 * g_tls_database_verify_chain_async:
 * @self: a #GTlsDatabase
 * @chain: a #GTlsCertificate chain
 * @purpose: the purpose that this certificate chain will be used for.
 * @identity: (allow-none): the expected peer identity
 * @interaction: (allow-none): used to interact with the user if necessary
 * @flags: additional verify flags
 * @cancellable: (allow-none): a #GCancellable, or %NULL
 * @callback: callback to call when the operation completes
 * @user_data: the data to pass to the callback function
 *
 * Asynchronously verify's a certificate chain after looking up and adding
 * any missing certificates to the chain. See g_tls_database_verify_chain()
 * for more information.
 *
 * Since: 2.30
 */
void
g_tls_database_verify_chain_async (GTlsDatabase           *self,
                                   GTlsCertificate        *chain,
                                   const gchar            *purpose,
                                   GSocketConnectable     *identity,
                                   GTlsInteraction        *interaction,
                                   GTlsDatabaseVerifyFlags flags,
                                   GCancellable           *cancellable,
                                   GAsyncReadyCallback     callback,
                                   gpointer                user_data)
{
  g_return_if_fail (G_IS_TLS_DATABASE (self));
  g_return_if_fail (G_IS_TLS_CERTIFICATE (chain));
  g_return_if_fail (purpose != NULL);
  g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
  g_return_if_fail (identity == NULL || G_IS_SOCKET_CONNECTABLE (identity));
  g_return_if_fail (callback != NULL);

  g_return_if_fail (G_TLS_DATABASE_GET_CLASS (self)->verify_chain_async);
  G_TLS_DATABASE_GET_CLASS (self)->verify_chain_async (self,
                                                       chain,
                                                       purpose,
                                                       identity,
                                                       interaction,
                                                       flags,
                                                       cancellable,
                                                       callback,
                                                       user_data);
}
Пример #3
0
/**
 * g_tls_interaction_ask_password_async:
 * @interaction: a #GTlsInteraction object
 * @password: a #GTlsPassword object
 * @cancellable: an optional #GCancellable cancellation object
 * @callback: (allow-none): will be called when the interaction completes
 * @user_data: (allow-none): data to pass to the @callback
 *
 * Run asynchronous interaction to ask the user for a password. In general,
 * g_tls_interaction_invoke_ask_password() should be used instead of this
 * function.
 *
 * Derived subclasses usually implement a password prompt, although they may
 * also choose to provide a password from elsewhere. The @password value will
 * be filled in and then @callback will be called. Alternatively the user may
 * abort this password request, which will usually abort the TLS connection.
 *
 * If the interaction is cancelled by the cancellation object, or by the
 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
 * not support immediate cancellation.
 *
 * Certain implementations may not support immediate cancellation.
 *
 * Since: 2.30
 */
void
g_tls_interaction_ask_password_async (GTlsInteraction    *interaction,
                                      GTlsPassword       *password,
                                      GCancellable       *cancellable,
                                      GAsyncReadyCallback callback,
                                      gpointer            user_data)
{
  GTlsInteractionClass *klass;
  GSimpleAsyncResult *res;

  g_return_if_fail (G_IS_TLS_INTERACTION (interaction));
  g_return_if_fail (G_IS_TLS_PASSWORD (password));
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));

  klass = G_TLS_INTERACTION_GET_CLASS (interaction);
  if (klass->ask_password_async)
    {
      g_return_if_fail (klass->ask_password_finish);
      (klass->ask_password_async) (interaction, password, cancellable,
                                   callback, user_data);
    }
  else
    {
      res = g_simple_async_result_new (G_OBJECT (interaction), callback, user_data,
                                       g_tls_interaction_ask_password_async);
      g_simple_async_result_complete_in_idle (res);
      g_object_unref (res);
    }
}
Пример #4
0
/**
 * g_tls_interaction_ask_password_async:
 * @interaction: a #GTlsInteraction object
 * @password: a #GTlsPassword object
 * @cancellable: an optional #GCancellable cancellation object
 * @callback: (allow-none): will be called when the interaction completes
 * @user_data: (allow-none): data to pass to the @callback
 *
 * Run asynchronous interaction to ask the user for a password. In general,
 * g_tls_interaction_invoke_ask_password() should be used instead of this
 * function.
 *
 * Derived subclasses usually implement a password prompt, although they may
 * also choose to provide a password from elsewhere. The @password value will
 * be filled in and then @callback will be called. Alternatively the user may
 * abort this password request, which will usually abort the TLS connection.
 *
 * If the interaction is cancelled by the cancellation object, or by the
 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
 * not support immediate cancellation.
 *
 * Certain implementations may not support immediate cancellation.
 *
 * Since: 2.30
 */
void
g_tls_interaction_ask_password_async (GTlsInteraction    *interaction,
                                      GTlsPassword       *password,
                                      GCancellable       *cancellable,
                                      GAsyncReadyCallback callback,
                                      gpointer            user_data)
{
  GTlsInteractionClass *klass;
  GTask *task;

  g_return_if_fail (G_IS_TLS_INTERACTION (interaction));
  g_return_if_fail (G_IS_TLS_PASSWORD (password));
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));

  klass = G_TLS_INTERACTION_GET_CLASS (interaction);
  if (klass->ask_password_async)
    {
      g_return_if_fail (klass->ask_password_finish);
      (klass->ask_password_async) (interaction, password, cancellable,
                                   callback, user_data);
    }
  else
    {
      task = g_task_new (interaction, cancellable, callback, user_data);
      g_task_set_source_tag (task, g_tls_interaction_ask_password_async);
      g_task_return_int (task, G_TLS_INTERACTION_UNHANDLED);
      g_object_unref (task);
    }
}
Пример #5
0
/**
 * g_tls_database_verify_chain:
 * @self: a #GTlsDatabase
 * @chain: a #GTlsCertificate chain
 * @purpose: the purpose that this certificate chain will be used for.
 * @identity: (allow-none): the expected peer identity
 * @interaction: (allow-none): used to interact with the user if necessary
 * @flags: additional verify flags
 * @cancellable: (allow-none): a #GCancellable, or %NULL
 * @error: (allow-none): a #GError, or %NULL
 *
 * Verify's a certificate chain after looking up and adding any missing
 * certificates to the chain.
 *
 * @chain is a chain of #GTlsCertificate objects each pointing to the next
 * certificate in the chain by its %issuer property. The chain may initially
 * consist of one or more certificates. After the verification process is
 * complete, @chain may be modified by adding missing certificates, or removing
 * extra certificates. If a certificate anchor was found, then it is added to
 * the @chain.
 *
 * @purpose describes the purpose (or usage) for which the certificate
 * is being used. Typically @purpose will be set to #G_TLS_DATABASE_PURPOSE_AUTHENTICATE_SERVER
 * which means that the certificate is being used to authenticate a server
 * (and we are acting as the client).
 *
 * The @identity is used to check for pinned certificates (trust exceptions)
 * in the database. These will override the normal verification process on a
 * host by host basis.
 *
 * Currently there are no @flags, and %G_TLS_DATABASE_VERIFY_NONE should be
 * used.
 *
 * This function can block, use g_tls_database_verify_chain_async() to perform
 * the verification operation asynchronously.
 *
 * Return value: the appropriate #GTlsCertificateFlags which represents the
 * result of verification.
 *
 * Since: 2.30
 */
GTlsCertificateFlags
g_tls_database_verify_chain (GTlsDatabase           *self,
                             GTlsCertificate        *chain,
                             const gchar            *purpose,
                             GSocketConnectable     *identity,
                             GTlsInteraction        *interaction,
                             GTlsDatabaseVerifyFlags flags,
                             GCancellable           *cancellable,
                             GError                **error)
{
  g_return_val_if_fail (G_IS_TLS_DATABASE (self), G_TLS_CERTIFICATE_GENERIC_ERROR);
  g_return_val_if_fail (G_IS_TLS_DATABASE (self),
                        G_TLS_CERTIFICATE_GENERIC_ERROR);
  g_return_val_if_fail (G_IS_TLS_CERTIFICATE (chain),
                        G_TLS_CERTIFICATE_GENERIC_ERROR);
  g_return_val_if_fail (purpose, G_TLS_CERTIFICATE_GENERIC_ERROR);
  g_return_val_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction),
                        G_TLS_CERTIFICATE_GENERIC_ERROR);
  g_return_val_if_fail (identity == NULL || G_IS_SOCKET_CONNECTABLE (identity),
                        G_TLS_CERTIFICATE_GENERIC_ERROR);
  g_return_val_if_fail (error == NULL || *error == NULL, G_TLS_CERTIFICATE_GENERIC_ERROR);

  g_return_val_if_fail (G_TLS_DATABASE_GET_CLASS (self)->verify_chain,
                        G_TLS_CERTIFICATE_GENERIC_ERROR);

  return G_TLS_DATABASE_GET_CLASS (self)->verify_chain (self,
                                                        chain,
                                                        purpose,
                                                        identity,
                                                        interaction,
                                                        flags,
                                                        cancellable,
                                                        error);
}
Пример #6
0
/**
 * g_dtls_connection_set_interaction:
 * @conn: a connection
 * @interaction: (allow-none): an interaction object, or %NULL
 *
 * Set the object that will be used to interact with the user. It will be used
 * for things like prompting the user for passwords.
 *
 * The @interaction argument will normally be a derived subclass of
 * #GTlsInteraction. %NULL can also be provided if no user interaction
 * should occur for this connection.
 *
 * Since: 2.48
 */
void
g_dtls_connection_set_interaction (GDtlsConnection *conn,
                                   GTlsInteraction *interaction)
{
  g_return_if_fail (G_IS_DTLS_CONNECTION (conn));
  g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));

  g_object_set (G_OBJECT (conn), "interaction", interaction, NULL);
}
Пример #7
0
/**
 * g_tls_interaction_ask_password:
 * @interaction: a #GTlsInteraction object
 * @password: a #GTlsPassword object
 * @cancellable: an optional #GCancellable cancellation object
 * @error: an optional location to place an error on failure
 *
 * Run synchronous interaction to ask the user for a password. In general,
 * g_tls_interaction_invoke_ask_password() should be used instead of this
 * function.
 *
 * Derived subclasses usually implement a password prompt, although they may
 * also choose to provide a password from elsewhere. The @password value will
 * be filled in and then @callback will be called. Alternatively the user may
 * abort this password request, which will usually abort the TLS connection.
 *
 * If the interaction is cancelled by the cancellation object, or by the
 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
 * not support immediate cancellation.
 *
 * Returns: The status of the ask password interaction.
 *
 * Since: 2.30
 */
GTlsInteractionResult
g_tls_interaction_ask_password (GTlsInteraction    *interaction,
                                GTlsPassword       *password,
                                GCancellable       *cancellable,
                                GError            **error)
{
  GTlsInteractionClass *klass;

  g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
  g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_INTERACTION_UNHANDLED);
  g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);

  klass = G_TLS_INTERACTION_GET_CLASS (interaction);
  if (klass->ask_password)
    return (klass->ask_password) (interaction, password, cancellable, error);
  else
    return G_TLS_INTERACTION_UNHANDLED;
}
Пример #8
0
/**
 * g_tls_database_lookup_certificates_issued_by:
 * @self: a #GTlsDatabase
 * @issuer_raw_dn: a #GByteArray which holds the DER encoded issuer DN.
 * @interaction: (allow-none): used to interact with the user if necessary
 * @flags: Flags which affect the lookup operation.
 * @cancellable: (allow-none): a #GCancellable, or %NULL
 * @error: (allow-none): a #GError, or %NULL
 *
 * Lookup certificates issued by this issuer in the database.
 *
 * This function can block, use g_tls_database_lookup_certificates_issued_by_async() to perform
 * the lookup operation asynchronously.
 *
 * Return value: (transfer full) (element-type GTlsCertificate): a newly allocated list of #GTlsCertificate
 * objects. Use g_object_unref() on each certificate, and g_list_free() on the release the list.
 *
 * Since: 2.30
 */
GList*
g_tls_database_lookup_certificates_issued_by (GTlsDatabase           *self,
                                              GByteArray             *issuer_raw_dn,
                                              GTlsInteraction        *interaction,
                                              GTlsDatabaseLookupFlags flags,
                                              GCancellable           *cancellable,
                                              GError                **error)
{
  g_return_val_if_fail (G_IS_TLS_DATABASE (self), NULL);
  g_return_val_if_fail (issuer_raw_dn, NULL);
  g_return_val_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction), NULL);
  g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
  g_return_val_if_fail (G_TLS_DATABASE_GET_CLASS (self)->lookup_certificates_issued_by, NULL);
  return G_TLS_DATABASE_GET_CLASS (self)->lookup_certificates_issued_by (self,
                                                                         issuer_raw_dn,
                                                                         interaction,
                                                                         flags,
                                                                         cancellable,
                                                                         error);
}
Пример #9
0
/**
 * g_tls_database_lookup_certificate_issuer:
 * @self: a #GTlsDatabase
 * @certificate: a #GTlsCertificate
 * @interaction: (allow-none): used to interact with the user if necessary
 * @flags: flags which affect the lookup operation
 * @cancellable: (allow-none): a #GCancellable, or %NULL
 * @error: (allow-none): a #GError, or %NULL
 *
 * Lookup the issuer of @certificate in the database.
 *
 * The %issuer property
 * of @certificate is not modified, and the two certificates are not hooked
 * into a chain.
 *
 * This function can block, use g_tls_database_lookup_certificate_issuer_async() to perform
 * the lookup operation asynchronously.
 *
 * Return value: (transfer full): a newly allocated issuer #GTlsCertificate,
 * or %NULL. Use g_object_unref() to release the certificate.
 *
 * Since: 2.30
 */
GTlsCertificate*
g_tls_database_lookup_certificate_issuer (GTlsDatabase           *self,
                                          GTlsCertificate        *certificate,
                                          GTlsInteraction        *interaction,
                                          GTlsDatabaseLookupFlags flags,
                                          GCancellable           *cancellable,
                                          GError                **error)
{
  g_return_val_if_fail (G_IS_TLS_DATABASE (self), NULL);
  g_return_val_if_fail (G_IS_TLS_CERTIFICATE (certificate), NULL);
  g_return_val_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction), NULL);
  g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
  g_return_val_if_fail (G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_issuer, NULL);
  return G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_issuer (self,
                                                                     certificate,
                                                                     interaction,
                                                                     flags,
                                                                     cancellable,
                                                                     error);
}
Пример #10
0
/**
 * g_tls_database_lookup_certificate_for_handle_async:
 * @self: a #GTlsDatabase
 * @handle: a certificate handle
 * @interaction: (allow-none): used to interact with the user if necessary
 * @flags: Flags which affect the lookup.
 * @cancellable: (allow-none): a #GCancellable, or %NULL
 * @callback: callback to call when the operation completes
 * @user_data: the data to pass to the callback function
 *
 * Asynchronously lookup a certificate by its handle in the database. See
 * g_tls_database_lookup_certificate_for_handle() for more information.
 *
 * Since: 2.30
 */
void
g_tls_database_lookup_certificate_for_handle_async (GTlsDatabase            *self,
                                                    const gchar             *handle,
                                                    GTlsInteraction         *interaction,
                                                    GTlsDatabaseLookupFlags  flags,
                                                    GCancellable            *cancellable,
                                                    GAsyncReadyCallback      callback,
                                                    gpointer                 user_data)
{
  g_return_if_fail (G_IS_TLS_DATABASE (self));
  g_return_if_fail (handle != NULL);
  g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
  g_return_if_fail (G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_for_handle_async);
  G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_for_handle_async (self,
                                                                               handle,
                                                                               interaction,
                                                                               flags,
                                                                               cancellable,
                                                                               callback,
                                                                               user_data);
}
Пример #11
0
/**
 * g_tls_database_lookup_certificates_issued_by_async:
 * @self: a #GTlsDatabase
 * @issuer_raw_dn: a #GByteArray which holds the DER encoded issuer DN.
 * @interaction: (allow-none): used to interact with the user if necessary
 * @flags: Flags which affect the lookup operation.
 * @cancellable: (allow-none): a #GCancellable, or %NULL
 * @callback: callback to call when the operation completes
 * @user_data: the data to pass to the callback function
 *
 * Asynchronously lookup certificates issued by this issuer in the database. See
 * g_tls_database_lookup_certificates_issued_by() for more information.
 *
 * The database may choose to hold a reference to the issuer byte array for the duration
 * of of this asynchronous operation. The byte array should not be modified during
 * this time.
 *
 * Since: 2.30
 */
void
g_tls_database_lookup_certificates_issued_by_async (GTlsDatabase           *self,
                                                    GByteArray             *issuer_raw_dn,
                                                    GTlsInteraction        *interaction,
                                                    GTlsDatabaseLookupFlags flags,
                                                    GCancellable           *cancellable,
                                                    GAsyncReadyCallback     callback,
                                                    gpointer                user_data)
{
  g_return_if_fail (G_IS_TLS_DATABASE (self));
  g_return_if_fail (issuer_raw_dn != NULL);
  g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
  g_return_if_fail (callback != NULL);
  g_return_if_fail (G_TLS_DATABASE_GET_CLASS (self)->lookup_certificates_issued_by_async);
  G_TLS_DATABASE_GET_CLASS (self)->lookup_certificates_issued_by_async (self,
                                                                        issuer_raw_dn,
                                                                        interaction,
                                                                        flags,
                                                                        cancellable,
                                                                        callback,
                                                                        user_data);
}
Пример #12
0
/**
 * g_tls_interaction_ask_password_finish:
 * @interaction: a #GTlsInteraction object
 * @result: the result passed to the callback
 * @error: an optional location to place an error on failure
 *
 * Complete an ask password user interaction request. This should be once
 * the g_tls_interaction_ask_password_async() completion callback is called.
 *
 * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsPassword passed
 * to g_tls_interaction_ask_password() will have its password filled in.
 *
 * If the interaction is cancelled by the cancellation object, or by the
 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
 * contains a %G_IO_ERROR_CANCELLED error code.
 *
 * Returns: The status of the ask password interaction.
 *
 * Since: 2.30
 */
GTlsInteractionResult
g_tls_interaction_ask_password_finish (GTlsInteraction    *interaction,
                                       GAsyncResult       *result,
                                       GError            **error)
{
  GTlsInteractionClass *klass;

  g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), G_TLS_INTERACTION_UNHANDLED);

  klass = G_TLS_INTERACTION_GET_CLASS (interaction);
  if (klass->ask_password_finish)
    {
      g_return_val_if_fail (klass->ask_password_async != NULL, G_TLS_INTERACTION_UNHANDLED);

      return (klass->ask_password_finish) (interaction, result, error);
    }
  else
    {
      g_return_val_if_fail (g_async_result_is_tagged (result, g_tls_interaction_ask_password_async), G_TLS_INTERACTION_UNHANDLED);

      return g_task_propagate_int (G_TASK (result), error);
    }
}
Пример #13
0
/**
 * g_tls_interaction_invoke_ask_password:
 * @interaction: a #GTlsInteraction object
 * @password: a #GTlsPassword object
 * @cancellable: an optional #GCancellable cancellation object
 * @error: an optional location to place an error on failure
 *
 * Invoke the interaction to ask the user for a password. It invokes this
 * interaction in the main loop, specifically the #GMainContext returned by
 * g_main_context_get_thread_default() when the interaction is created. This
 * is called by called by #GTlsConnection or #GTlsDatabase to ask the user
 * for a password.
 *
 * Derived subclasses usually implement a password prompt, although they may
 * also choose to provide a password from elsewhere. The @password value will
 * be filled in and then @callback will be called. Alternatively the user may
 * abort this password request, which will usually abort the TLS connection.
 *
 * The implementation can either be a synchronous (eg: modal dialog) or an
 * asynchronous one (eg: modeless dialog). This function will take care of
 * calling which ever one correctly.
 *
 * If the interaction is cancelled by the cancellation object, or by the
 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
 * not support immediate cancellation.
 *
 * Returns: The status of the ask password interaction.
 *
 * Since: 2.30
 */
GTlsInteractionResult
g_tls_interaction_invoke_ask_password (GTlsInteraction    *interaction,
                                       GTlsPassword       *password,
                                       GCancellable       *cancellable,
                                       GError            **error)
{
  GTlsInteractionResult result;
  InvokeClosure *closure;
  GTlsInteractionClass *klass;

  g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
  g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_INTERACTION_UNHANDLED);
  g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);

  closure = invoke_closure_new (interaction, G_OBJECT (password), cancellable);

  klass = G_TLS_INTERACTION_GET_CLASS (interaction);
  if (klass->ask_password)
    {
      g_main_context_invoke (interaction->priv->context,
                             on_invoke_ask_password_sync, closure);
      result = invoke_closure_wait_and_free (closure, error);
    }
  else if (klass->ask_password_async)
    {
      g_return_val_if_fail (klass->ask_password_finish, G_TLS_INTERACTION_UNHANDLED);
      g_main_context_invoke (interaction->priv->context,
                             on_invoke_ask_password_async_as_sync, closure);

      /*
       * Handle the case where we've been called from within the main context
       * or in the case where the main context is not running. This approximates
       * the behavior of a modal dialog.
       */
      if (g_main_context_acquire (interaction->priv->context))
        {
          while (!closure->complete)
            {
              g_mutex_unlock (closure->mutex);
              g_main_context_iteration (interaction->priv->context, TRUE);
              g_mutex_lock (closure->mutex);
            }
          g_main_context_release (interaction->priv->context);

          if (closure->error)
            {
              g_propagate_error (error, closure->error);
              closure->error = NULL;
            }

          result = closure->result;
          invoke_closure_free (closure);
        }

      /*
       * Handle the case where we're in a different thread than the main
       * context and a main loop is running.
       */
      else
        {
          result = invoke_closure_wait_and_free (closure, error);
        }
    }
  else
    {
      result = G_TLS_INTERACTION_UNHANDLED;
      invoke_closure_free (closure);
    }

  return result;
}