static gchar * get_remote_address (GIOStream *io) { GSocketAddress *remote = NULL; GSocketConnection *connection = NULL; GIOStream *base; gchar *result = NULL; if (G_IS_TLS_CONNECTION (io)) { g_object_get (io, "base-io-stream", &base, NULL); if (G_IS_SOCKET_CONNECTION (base)) connection = g_object_ref (base); g_object_unref (base); } else if (G_IS_SOCKET_CONNECTION (io)) { connection = g_object_ref (io); } if (connection) remote = g_socket_connection_get_remote_address (connection, NULL); if (remote && G_IS_INET_SOCKET_ADDRESS (remote)) result = g_inet_address_to_string (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (remote))); if (remote) g_object_unref (remote); if (connection) g_object_unref (connection); return result; }
static gchar * describe_certificate_errors (GIOStream *io) { GTlsCertificateFlags flags; GString *str; if (!G_IS_TLS_CONNECTION (io)) return NULL; flags = g_tls_connection_get_peer_certificate_errors (G_TLS_CONNECTION (io)); if (flags == 0) return NULL; str = g_string_new (""); if (flags & G_TLS_CERTIFICATE_UNKNOWN_CA) { g_string_append (str, "untrusted-issuer "); flags &= ~G_TLS_CERTIFICATE_UNKNOWN_CA; } if (flags & G_TLS_CERTIFICATE_BAD_IDENTITY) { g_string_append (str, "bad-server-identity "); flags &= ~G_TLS_CERTIFICATE_BAD_IDENTITY; } if (flags & G_TLS_CERTIFICATE_NOT_ACTIVATED) { g_string_append (str, "not-yet-valid "); flags &= ~G_TLS_CERTIFICATE_NOT_ACTIVATED; } if (flags & G_TLS_CERTIFICATE_EXPIRED) { g_string_append (str, "expired "); flags &= ~G_TLS_CERTIFICATE_EXPIRED; } if (flags & G_TLS_CERTIFICATE_REVOKED) { g_string_append (str, "revoked "); flags &= ~G_TLS_CERTIFICATE_REVOKED; } if (flags & G_TLS_CERTIFICATE_INSECURE) { g_string_append (str, "insecure "); flags &= ~G_TLS_CERTIFICATE_INSECURE; } if (flags & G_TLS_CERTIFICATE_GENERIC_ERROR) { g_string_append (str, "generic-error "); flags &= ~G_TLS_CERTIFICATE_GENERIC_ERROR; } if (flags != 0) { g_string_append (str, "..."); } return g_string_free (str, FALSE); }
/** * g_tls_connection_set_certificate: * @conn: a #GTlsConnection * @certificate: the certificate to use for @conn * * This sets the certificate that @conn will present to its peer * during the TLS handshake. For a #GTlsServerConnection, it is * mandatory to set this, and that will normally be done at construct * time. * * For a #GTlsClientConnection, 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_tls_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_tls_client_connection_get_accepted_cas() will return * non-%NULL.) * * Since: 2.28 */ void g_tls_connection_set_certificate (GTlsConnection *conn, GTlsCertificate *certificate) { g_return_if_fail (G_IS_TLS_CONNECTION (conn)); g_return_if_fail (G_IS_TLS_CERTIFICATE (certificate)); g_object_set (G_OBJECT (conn), "certificate", certificate, NULL); }
/** * g_tls_connection_handshake: * @conn: a #GTlsConnection * @cancellable: a #GCancellable, or %NULL * @error: a #GError, or %NULL * * Attempts a TLS handshake on @conn. * * On the client side, it is never necessary to call this method; * although the connection needs to perform a handshake after * connecting (or after sending a "STARTTLS"-type command) and may * need to rehandshake later if the server requests it, * #GTlsConnection will handle this for you automatically when you try * to send or receive data on the connection. However, you can call * g_tls_connection_handshake() manually if you want to know for sure * whether the initial handshake succeeded or failed (as opposed to * just immediately trying to write to @conn's output stream, in which * case if it fails, it may not be possible to tell if it failed * before or after completing the handshake). * * Likewise, on the server side, although a handshake is necessary at * the beginning of the communication, you do not need to call this * function explicitly unless you want clearer error reporting. * However, you may call g_tls_connection_handshake() later on to * renegotiate parameters (encryption methods, etc) with the client. * * #GTlsConnection::accept_certificate may be emitted during the * handshake. * * Return value: success or failure * * Since: 2.28 */ gboolean g_tls_connection_handshake (GTlsConnection *conn, GCancellable *cancellable, GError **error) { g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), FALSE); return G_TLS_CONNECTION_GET_CLASS (conn)->handshake (conn, cancellable, error); }
/** * g_tls_connection_handshake_finish: * @conn: a #GTlsConnection * @result: a #GAsyncResult. * @error: a #GError pointer, or %NULL * * Finish an asynchronous TLS handshake operation. See * g_tls_connection_handshake() for more information. * * Return value: %TRUE on success, %FALSE on failure, in which * case @error will be set. * * Since: 2.28 */ gboolean g_tls_connection_handshake_finish (GTlsConnection *conn, GAsyncResult *result, GError **error) { g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), FALSE); return G_TLS_CONNECTION_GET_CLASS (conn)->handshake_finish (conn, result, error); }
static void soup_socket_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object); switch (prop_id) { case PROP_LOCAL_ADDRESS: g_value_set_object (value, soup_socket_get_local_address (SOUP_SOCKET (object))); break; case PROP_REMOTE_ADDRESS: g_value_set_object (value, soup_socket_get_remote_address (SOUP_SOCKET (object))); break; case PROP_NON_BLOCKING: g_value_set_boolean (value, priv->non_blocking); break; case PROP_IS_SERVER: g_value_set_boolean (value, priv->is_server); break; case PROP_SSL_CREDENTIALS: g_value_set_pointer (value, priv->ssl_creds); break; case PROP_SSL_STRICT: g_value_set_boolean (value, priv->ssl_strict); break; case PROP_SSL_FALLBACK: g_value_set_boolean (value, priv->ssl_fallback); break; case PROP_TRUSTED_CERTIFICATE: g_value_set_boolean (value, priv->tls_errors == 0); break; case PROP_ASYNC_CONTEXT: g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL); break; case PROP_USE_THREAD_CONTEXT: g_value_set_boolean (value, priv->use_thread_context); break; case PROP_TIMEOUT: g_value_set_uint (value, priv->timeout); break; case PROP_TLS_CERTIFICATE: if (G_IS_TLS_CONNECTION (priv->conn)) g_value_set_object (value, g_tls_connection_get_peer_certificate (G_TLS_CONNECTION (priv->conn))); else g_value_set_object (value, NULL); break; case PROP_TLS_ERRORS: g_value_set_flags (value, priv->tls_errors); break; case PROP_PROXY_RESOLVER: g_value_set_object (value, priv->proxy_resolver); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
/** * g_tls_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.30 */ void g_tls_connection_set_interaction (GTlsConnection *conn, GTlsInteraction *interaction) { g_return_if_fail (G_IS_TLS_CONNECTION (conn)); g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction)); g_object_set (G_OBJECT (conn), "interaction", interaction, NULL); }
/** * g_tls_connection_set_use_system_certdb: * @conn: a #GTlsConnection * @use_system_certdb: whether to use the system certificate database * * Sets whether @conn uses the system certificate database to verify * peer certificates. This is %TRUE by default. If set to %FALSE, then * peer certificate validation will always set the * %G_TLS_CERTIFICATE_UNKNOWN_CA error (meaning * #GTlsConnection::accept-certificate will always be emitted on * client-side connections, unless that bit is not set in * #GTlsClientConnection:validation-flags). * * Deprecated: 2.30: Use g_tls_connection_set_database() instead */ void g_tls_connection_set_use_system_certdb (GTlsConnection *conn, gboolean use_system_certdb) { g_return_if_fail (G_IS_TLS_CONNECTION (conn)); g_object_set (G_OBJECT (conn), "use-system-certdb", use_system_certdb, NULL); }
/** * g_tls_connection_get_peer_certificate_errors: * @conn: a #GTlsConnection * * Gets the errors associated with validating @conn's peer's * certificate, after the handshake has completed. (It is not set * during the emission of #GTlsConnection::accept-certificate.) * * Return value: @conn's peer's certificate errors * * Since: 2.28 */ GTlsCertificateFlags g_tls_connection_get_peer_certificate_errors (GTlsConnection *conn) { GTlsCertificateFlags errors; g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), 0); g_object_get (G_OBJECT (conn), "peer-certificate-errors", &errors, NULL); return errors; }
/** * g_tls_connection_set_rehandshake_mode: * @conn: a #GTlsConnection * @mode: the rehandshaking mode * * Sets how @conn behaves with respect to rehandshaking requests. * * %G_TLS_REHANDSHAKE_NEVER means that it will never agree to * rehandshake after the initial handshake is complete. (For a client, * this means it will refuse rehandshake requests from the server, and * for a server, this means it will close the connection with an error * if the client attempts to rehandshake.) * * %G_TLS_REHANDSHAKE_SAFELY means that the connection will allow a * rehandshake only if the other end of the connection supports the * TLS <literal>renegotiation_info</literal> extension. This is the * default behavior, but means that rehandshaking will not work * against older implementations that do not support that extension. * * %G_TLS_REHANDSHAKE_UNSAFELY means that the connection will allow * rehandshaking even without the * <literal>renegotiation_info</literal> extension. On the server side * in particular, this is not recommended, since it leaves the server * open to certain attacks. However, this mode is necessary if you * need to allow renegotiation with older client software. * * Since: 2.28 */ void g_tls_connection_set_rehandshake_mode (GTlsConnection *conn, GTlsRehandshakeMode mode) { g_return_if_fail (G_IS_TLS_CONNECTION (conn)); g_object_set (G_OBJECT (conn), "rehandshake-mode", mode, NULL); }
/** * g_tls_connection_set_require_close_notify: * @conn: a #GTlsConnection * @require_close_notify: whether or not to require close notification * * Sets whether or not @conn expects a proper TLS close notification * before the connection is closed. If this is %TRUE (the default), * then @conn will expect to receive a TLS close notification from its * peer before the connection is closed, and will return a * %G_TLS_ERROR_EOF error if the connection is closed without proper * notification (since this may indicate a network error, or * man-in-the-middle attack). * * In some protocols, the application will know whether or not the * connection was closed cleanly based on application-level data * (because the application-level data includes a length field, or is * somehow self-delimiting); in this case, the close notify is * redundant and sometimes omitted. (TLS 1.1 explicitly allows this; * in TLS 1.0 it is technically an error, but often done anyway.) You * can use g_tls_connection_set_require_close_notify() to tell @conn * to allow an "unannounced" connection close, in which case the close * will show up as a 0-length read, as in a non-TLS * #GSocketConnection, and it is up to the application to check that * the data has been fully received. * * Note that this only affects the behavior when the peer closes the * connection; when the application calls g_io_stream_close() itself * on @conn, this will send a close notification regardless of the * setting of this property. If you explicitly want to do an unclean * close, you can close @conn's #GTlsConnection:base-io-stream rather * than closing @conn itself. * * Since: 2.28 */ void g_tls_connection_set_require_close_notify (GTlsConnection *conn, gboolean require_close_notify) { g_return_if_fail (G_IS_TLS_CONNECTION (conn)); g_object_set (G_OBJECT (conn), "require-close-notify", require_close_notify, NULL); }
/** * g_tls_connection_set_database: * @conn: a #GTlsConnection * @database: a #GTlsDatabase * * Sets the certificate database that is used to verify peer certificates. * This is set to the default database by default. See * g_tls_backend_get_default_database(). If set to %NULL, then * peer certificate validation will always set the * %G_TLS_CERTIFICATE_UNKNOWN_CA error (meaning * #GTlsConnection::accept-certificate will always be emitted on * client-side connections, unless that bit is not set in * #GTlsClientConnection:validation-flags). * * Since: 2.30 */ void g_tls_connection_set_database (GTlsConnection *conn, GTlsDatabase *database) { g_return_if_fail (G_IS_TLS_CONNECTION (conn)); g_return_if_fail (database == NULL || G_IS_TLS_DATABASE (database)); g_object_set (G_OBJECT (conn), "database", database, NULL); }
/** * g_tls_connection_get_use_system_certdb: * @conn: a #GTlsConnection * * Gets whether @conn uses the system certificate database to verify * peer certificates. See g_tls_connection_set_use_system_certdb(). * * Return value: whether @conn uses the system certificate database * * Deprecated: 2.30: Use g_tls_connection_get_database() instead */ gboolean g_tls_connection_get_use_system_certdb (GTlsConnection *conn) { gboolean use_system_certdb; g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), TRUE); g_object_get (G_OBJECT (conn), "use-system-certdb", &use_system_certdb, NULL); return use_system_certdb; }
/** * g_tls_connection_get_rehandshake_mode: * @conn: a #GTlsConnection * * Gets @conn rehandshaking mode. See * g_tls_connection_set_rehandshake_mode() for details. * * Return value: @conn's rehandshaking mode * * Since: 2.28 */ GTlsRehandshakeMode g_tls_connection_get_rehandshake_mode (GTlsConnection *conn) { GTlsRehandshakeMode mode; g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), G_TLS_REHANDSHAKE_NEVER); g_object_get (G_OBJECT (conn), "rehandshake-mode", &mode, NULL); return mode; }
/** * g_tls_connection_get_require_close_notify: * @conn: a #GTlsConnection * * Tests whether or not @conn expects a proper TLS close notification * when the connection is closed. See * g_tls_connection_set_require_close_notify() for details. * * Return value: %TRUE if @conn requires a proper TLS close * notification. * * Since: 2.28 */ gboolean g_tls_connection_get_require_close_notify (GTlsConnection *conn) { gboolean require_close_notify; g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), TRUE); g_object_get (G_OBJECT (conn), "require-close-notify", &require_close_notify, NULL); return require_close_notify; }
/** * g_tls_connection_handshake_async: * @conn: a #GTlsConnection * @io_priority: the <link linkend="io-priority">I/O priority</link> * of the request. * @cancellable: a #GCancellable, or %NULL * @callback: callback to call when the handshake is complete * @user_data: the data to pass to the callback function * * Asynchronously performs a TLS handshake on @conn. See * g_tls_connection_handshake() for more information. * * Since: 2.28 */ void g_tls_connection_handshake_async (GTlsConnection *conn, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail (G_IS_TLS_CONNECTION (conn)); G_TLS_CONNECTION_GET_CLASS (conn)->handshake_async (conn, io_priority, cancellable, callback, user_data); }
/** * g_tls_connection_get_peer_certificate: * @conn: a #GTlsConnection * * Gets @conn's peer's certificate after the handshake has completed. * (It is not set during the emission of * #GTlsConnection::accept-certificate.) * * Return value: (transfer none): @conn's peer's certificate, or %NULL * * Since: 2.28 */ GTlsCertificate * g_tls_connection_get_peer_certificate (GTlsConnection *conn) { GTlsCertificate *peer_certificate; g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), NULL); g_object_get (G_OBJECT (conn), "peer-certificate", &peer_certificate, NULL); if (peer_certificate) g_object_unref (peer_certificate); return peer_certificate; }
/** * g_tls_connection_get_interaction: * @conn: a connection * * Get the object that will be used to interact with the user. It will be used * for things like prompting the user for passwords. If %NULL is returned, then * no user interaction will occur for this connection. * * Returns: (transfer none): The interaction object. * * Since: 2.30 */ GTlsInteraction * g_tls_connection_get_interaction (GTlsConnection *conn) { GTlsInteraction *interaction = NULL; g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), NULL); g_object_get (G_OBJECT (conn), "interaction", &interaction, NULL); if (interaction) g_object_unref (interaction); return interaction; }
/** * g_tls_connection_get_database: * @conn: a #GTlsConnection * * Gets the certificate database that @conn uses to verify * peer certificates. See g_tls_connection_set_database(). * * Return value: (transfer none): the certificate database that @conn uses or %NULL * * Since: 2.30 */ GTlsDatabase* g_tls_connection_get_database (GTlsConnection *conn) { GTlsDatabase *database = NULL; g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), NULL); g_object_get (G_OBJECT (conn), "database", &database, NULL); if (database) g_object_unref (database); return database; }
static void initialize_io (CockpitStream *self) { GInputStream *is; GOutputStream *os; g_return_if_fail (self->priv->in_source == NULL); is = g_io_stream_get_input_stream (self->priv->io); os = g_io_stream_get_output_stream (self->priv->io); if (!G_IS_POLLABLE_INPUT_STREAM (is) || !g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (is)) || !G_IS_POLLABLE_OUTPUT_STREAM (os) || !g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (os))) { g_warning ("%s: stream is not pollable", self->priv->name); close_immediately (self, "internal-error"); return; } if (self->priv->connecting) { cockpit_connectable_unref (self->priv->connecting); self->priv->connecting = NULL; } self->priv->in_source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (is), NULL); g_source_set_name (self->priv->in_source, "stream-input"); g_source_set_callback (self->priv->in_source, (GSourceFunc)dispatch_input, self, NULL); g_source_attach (self->priv->in_source, self->priv->context); if (G_IS_TLS_CONNECTION (self->priv->io)) { self->priv->sig_accept_cert = g_signal_connect (G_TLS_CONNECTION (self->priv->io), "accept-certificate", G_CALLBACK (on_rejected_certificate), self); } else { self->priv->sig_accept_cert = 0; } start_output (self); g_signal_emit (self, cockpit_stream_sig_open, 0); }
static void e_soup_ssl_trust_network_event_cb (SoupMessage *msg, GSocketClientEvent event, GIOStream *connection, gpointer user_data) { ESoupSslTrustData *handler = user_data; /* It's either a GTlsConnection or a GTcpConnection */ if (event == G_SOCKET_CLIENT_TLS_HANDSHAKING && G_IS_TLS_CONNECTION (connection)) { g_signal_connect_closure ( G_TLS_CONNECTION (connection), "accept-certificate", handler->accept_certificate_closure, FALSE); } }
static void on_socket_connect (GObject *object, GAsyncResult *result, gpointer user_data) { CockpitWebSocketStream *self = COCKPIT_WEB_SOCKET_STREAM (user_data); CockpitChannel *channel = COCKPIT_CHANNEL (self); const gchar *problem = "protocol-error"; gchar **protocols = NULL; GList *l, *names = NULL; GError *error = NULL; JsonObject *options; JsonObject *headers; const gchar *value; JsonNode *node; GIOStream *io; io = cockpit_connect_stream_finish (result, &error); if (error) { problem = cockpit_stream_problem (error, self->origin, "couldn't connect", cockpit_channel_close_options (channel)); cockpit_channel_close (channel, problem); goto out; } options = cockpit_channel_get_options (channel); if (!cockpit_json_get_strv (options, "protocols", NULL, &protocols)) { cockpit_channel_fail (channel, "protocol-error", "%s: invalid \"protocol\" value in WebSocket stream request", self->origin); goto out; } if (G_IS_TLS_CONNECTION (io)) { self->sig_accept_cert = g_signal_connect (G_TLS_CONNECTION (io), "accept-certificate", G_CALLBACK (on_rejected_certificate), self); } else { self->sig_accept_cert = 0; } self->client = web_socket_client_new_for_stream (self->url, self->origin, (const gchar **)protocols, io); node = json_object_get_member (options, "headers"); if (node) { if (!JSON_NODE_HOLDS_OBJECT (node)) { cockpit_channel_fail (channel, "protocol-error", "%s: invalid \"headers\" field in WebSocket stream request", self->origin); goto out; } headers = json_node_get_object (node); names = json_object_get_members (headers); for (l = names; l != NULL; l = g_list_next (l)) { node = json_object_get_member (headers, l->data); if (!node || !JSON_NODE_HOLDS_VALUE (node) || json_node_get_value_type (node) != G_TYPE_STRING) { cockpit_channel_fail (channel, "protocol-error", "%s: invalid header value in WebSocket stream request: %s", self->origin, (gchar *)l->data); goto out; } value = json_node_get_string (node); g_debug ("%s: sending header: %s %s", self->origin, (gchar *)l->data, value); web_socket_client_include_header (WEB_SOCKET_CLIENT (self->client), l->data, value); } } self->sig_open = g_signal_connect (self->client, "open", G_CALLBACK (on_web_socket_open), self); self->sig_message = g_signal_connect (self->client, "message", G_CALLBACK (on_web_socket_message), self); self->sig_closing = g_signal_connect (self->client, "closing", G_CALLBACK (on_web_socket_closing), self); self->sig_close = g_signal_connect (self->client, "close", G_CALLBACK (on_web_socket_close), self); self->sig_error = g_signal_connect (self->client, "error", G_CALLBACK (on_web_socket_error), self); problem = NULL; out: g_clear_error (&error); g_strfreev (protocols); if (io) g_object_unref (io); g_list_free (names); }