Ejemplo n.º 1
0
/* Prompts the user to accept the certificate as it failed due to the
 * passed errors.
 */
static void
request_accept_certificate(const gchar *identity, GTlsCertificate *peer_cert,
		GTlsCertificateFlags errors)
{
	UserCertRequestData *data;
	gchar *primary;

	g_return_if_fail(identity != NULL && identity[0] != '\0');
	g_return_if_fail(G_IS_TLS_CERTIFICATE(peer_cert));
	g_return_if_fail(errors != 0);

	data = g_new(UserCertRequestData, 1);
	data->identity = g_strdup(identity);
	data->cert = g_object_ref(peer_cert);

	primary = g_strdup_printf(_("Accept certificate for %s?"), identity);
	purple_request_certificate(data,
			_("TLS Certificate Verification"),
			primary,
			tls_certificate_flags_to_reason(errors),
			data->cert,
			_("Accept"), G_CALLBACK(user_cert_request_accept_cb),
			_("Reject"), G_CALLBACK(user_cert_request_deny_cb),
			data);
	g_free(primary);
}
Ejemplo n.º 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);
}
Ejemplo n.º 3
0
gboolean
purple_tls_certificate_trust(const gchar *id, GTlsCertificate *certificate,
		GError **error)
{
	gchar *path;
	gchar *pem = NULL;
	gboolean ret;

	g_return_val_if_fail(id != NULL && id[0] != '\0', FALSE);
	g_return_val_if_fail(G_IS_TLS_CERTIFICATE(certificate), FALSE);

	/* Ensure certificate directory exists */

	if (!ensure_certificate_dir(error)) {
		return FALSE;
	}

	/* Get the text representation of the certificate */

	g_object_get(certificate, "certificate-pem", &pem, NULL);
	g_return_val_if_fail(pem != NULL, FALSE);

	/* Save certificate text to a fail */

	path = make_certificate_path(id);
	ret = g_file_set_contents(path, pem, -1, error);
	g_free(path);
	g_free(pem);

	return ret;
}
Ejemplo n.º 4
0
static void testLoadFailedWithTLSErrors(TLSErrorsTest* test, gconstpointer)
{
    WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
    WebKitTLSErrorsPolicy originalPolicy = webkit_web_context_get_tls_errors_policy(context);
    webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_FAIL);

    // The load-failed-with-tls-errors signal should be emitted when there is a TLS failure.
    test->loadURI(kHttpsServer->getURIForPath("/test-tls/").data());
    test->waitUntilLoadFinished();
    g_assert(G_IS_TLS_CERTIFICATE(test->certificate()));
    g_assert_cmpuint(test->tlsErrors(), ==, G_TLS_CERTIFICATE_UNKNOWN_CA);
    g_assert_cmpstr(test->host(), ==, soup_uri_get_host(kHttpsServer->baseURI()));
    g_assert_cmpint(test->m_loadEvents[0], ==, LoadTrackingTest::ProvisionalLoadStarted);
    g_assert_cmpint(test->m_loadEvents[1], ==, LoadTrackingTest::LoadFailedWithTLSErrors);
    g_assert_cmpint(test->m_loadEvents[2], ==, LoadTrackingTest::LoadFinished);

    // Test allowing an exception for this certificate on this host.
    webkit_web_context_allow_tls_certificate_for_host(context, test->certificate(), test->host());
    // The page should now load without errors.
    test->loadURI(kHttpsServer->getURIForPath("/test-tls/").data());
    test->waitUntilLoadFinished();

    g_assert_cmpint(test->m_loadEvents[0], ==, LoadTrackingTest::ProvisionalLoadStarted);
    g_assert_cmpint(test->m_loadEvents[1], ==, LoadTrackingTest::LoadCommitted);
    g_assert_cmpint(test->m_loadEvents[2], ==, LoadTrackingTest::LoadFinished);
    g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, TLSExpectedSuccessTitle);

    webkit_web_context_set_tls_errors_policy(context, originalPolicy);
}
Ejemplo n.º 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);
}
Ejemplo n.º 6
0
static void
g_tls_database_real_lookup_certificate_issuer_async (GTlsDatabase           *self,
                                                     GTlsCertificate        *certificate,
                                                     GTlsInteraction        *interaction,
                                                     GTlsDatabaseLookupFlags flags,
                                                     GCancellable           *cancellable,
                                                     GAsyncReadyCallback     callback,
                                                     gpointer                user_data)
{
  GSimpleAsyncResult *res;
  AsyncLookupCertificateIssuer *args;

  g_return_if_fail (G_IS_TLS_CERTIFICATE (certificate));
  g_return_if_fail (callback != NULL);

  args = g_slice_new0 (AsyncLookupCertificateIssuer);
  args->certificate = g_object_ref (certificate);
  args->flags = flags;
  args->interaction = interaction ? g_object_ref (interaction) : NULL;

  res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
                                   g_tls_database_real_lookup_certificate_issuer_async);
  g_simple_async_result_set_op_res_gpointer (res, args, async_lookup_certificate_issuer_free);
  g_simple_async_result_run_in_thread (res, async_lookup_certificate_issuer_thread,
                                       G_PRIORITY_DEFAULT, cancellable);
  g_object_unref (res);
}
Ejemplo n.º 7
0
/**
 * g_dtls_connection_set_certificate:
 * @conn: a #GDtlsConnection
 * @certificate: the certificate to use for @conn
 *
 * This sets the certificate that @conn will present to its peer
 * during the TLS handshake. For a #GDtlsServerConnection, it is
 * mandatory to set this, and that will normally be done at construct
 * time.
 *
 * For a #GDtlsClientConnection, this is optional. If a handshake fails
 * with %G_TLS_ERROR_CERTIFICATE_REQUIRED, that means that the server
 * requires a certificate, and if you try connecting again, you should
 * call this method first. You can call
 * g_dtls_client_connection_get_accepted_cas() on the failed connection
 * to get a list of Certificate Authorities that the server will
 * accept certificates from.
 *
 * (It is also possible that a server will allow the connection with
 * or without a certificate; in that case, if you don't provide a
 * certificate, you can tell that the server requested one by the fact
 * that g_dtls_client_connection_get_accepted_cas() will return
 * non-%NULL.)
 *
 * Since: 2.48
 */
void
g_dtls_connection_set_certificate (GDtlsConnection *conn,
                                   GTlsCertificate *certificate)
{
  g_return_if_fail (G_IS_DTLS_CONNECTION (conn));
  g_return_if_fail (G_IS_TLS_CERTIFICATE (certificate));

  g_object_set (G_OBJECT (conn), "certificate", certificate, NULL);
}
Ejemplo n.º 8
0
/**
 * g_tls_database_create_certificate_handle:
 * @self: a #GTlsDatabase
 * @certificate: certificate for which to create a handle.
 *
 * Create a handle string for the certificate. The database will only be able
 * to create a handle for certificates that originate from the database. In
 * cases where the database cannot create a handle for a certificate, %NULL
 * will be returned.
 *
 * This handle should be stable across various instances of the application,
 * and between applications. If a certificate is modified in the database,
 * then it is not guaranteed that this handle will continue to point to it.
 *
 * Returns: (allow-none): a newly allocated string containing the handle.
 * Since: 2.30
 */
gchar*
g_tls_database_create_certificate_handle (GTlsDatabase            *self,
                                          GTlsCertificate         *certificate)
{
  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 (G_TLS_DATABASE_GET_CLASS (self)->create_certificate_handle, NULL);
  return G_TLS_DATABASE_GET_CLASS (self)->create_certificate_handle (self,
                                                                     certificate);
}
Ejemplo n.º 9
0
/* Called when a GTlsConnection (which this handler has been connected to)
 *   has an error validating its certificate.
 * Returns TRUE if the certificate is already trusted, so the connection
 *   can continue.
 * Returns FALSE if the certificate is not trusted, causing the
 *   connection's handshake to fail, and then prompts the user to accept
 *   the certificate.
 */
static gboolean
accept_certificate_cb(GTlsConnection *conn, GTlsCertificate *peer_cert,
		GTlsCertificateFlags errors, gpointer user_data)
{
	GTlsCertificate *trusted_cert;
	GSocketConnectable *connectable;
	const gchar *identity;

	g_return_val_if_fail(G_IS_TLS_CLIENT_CONNECTION(conn), FALSE);
	g_return_val_if_fail(G_IS_TLS_CERTIFICATE(peer_cert), FALSE);

	/* Get the certificate identity from the GTlsClientConnection */

	connectable = g_tls_client_connection_get_server_identity(
			G_TLS_CLIENT_CONNECTION(conn));

	g_return_val_if_fail(G_IS_SOCKET_CONNECTABLE(connectable), FALSE);

	/* identity is owned by the connectable */
	if (G_IS_NETWORK_ADDRESS(connectable)) {
		identity = g_network_address_get_hostname(
				G_NETWORK_ADDRESS(connectable));
	} else if (G_IS_NETWORK_SERVICE(connectable)) {
		identity = g_network_service_get_domain(
				G_NETWORK_SERVICE(connectable));
	} else {
		g_return_val_if_reached(FALSE);
	}

	/* See if a trusted certificate matching the peer certificate exists */

	trusted_cert = purple_tls_certificate_new_from_id(identity, NULL);

	if (trusted_cert != NULL &&
			g_tls_certificate_is_same(peer_cert, trusted_cert)) {
		/* It's manually trusted. Accept certificate */
		g_object_unref(trusted_cert);
		return TRUE;
	}

	g_clear_object(&trusted_cert);

	/* Certificate failed and isn't trusted.
	 * Fail certificate and prompt user.
	 */

	request_accept_certificate(identity, peer_cert, errors);

	return FALSE;
}
Ejemplo n.º 10
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);
}
Ejemplo n.º 11
0
/**
 * g_tls_database_lookup_certificate_issuer_async:
 * @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
 * @callback: callback to call when the operation completes
 * @user_data: the data to pass to the callback function
 *
 * Asynchronously lookup the issuer of @certificate in the database. See
 * g_tls_database_lookup_certificate_issuer() for more information.
 *
 * Since: 2.30
 */
void
g_tls_database_lookup_certificate_issuer_async (GTlsDatabase           *self,
                                                GTlsCertificate        *certificate,
                                                GTlsInteraction        *interaction,
                                                GTlsDatabaseLookupFlags 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 (certificate));
  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_certificate_issuer_async);
  G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_issuer_async (self,
                                                        certificate,
                                                        interaction,
                                                        flags,
                                                        cancellable,
                                                        callback,
                                                        user_data);
}