[gnome-network-displays/cc-tmp: 3/80] cc: tls handshake fails
- From: Benjamin Berg <bberg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-network-displays/cc-tmp: 3/80] cc: tls handshake fails
- Date: Fri, 9 Sep 2022 12:03:48 +0000 (UTC)
commit 5acf620fe3b2d84971698ae5e829241a742454a9
Author: Anupam Kumar <kyteinsky gmail com>
Date: Tue Jul 12 01:27:18 2022 +0530
cc: tls handshake fails
src/nd-cc-sink.c | 347 +++++++++++++++++++++++++++++++++++--------------------
1 file changed, 221 insertions(+), 126 deletions(-)
---
diff --git a/src/nd-cc-sink.c b/src/nd-cc-sink.c
index e301dcd..64a7f57 100644
--- a/src/nd-cc-sink.c
+++ b/src/nd-cc-sink.c
@@ -41,7 +41,7 @@ struct _NdCCSink
gchar *remote_name;
GSocketClient *comm_client;
- GSocketConnection *comm_client_conn;
+ GIOStream *connection;
WfdServer *server;
guint server_source_id;
@@ -77,21 +77,26 @@ G_DEFINE_TYPE_EXTENDED (NdCCSink, nd_cc_sink, G_TYPE_OBJECT, 0,
static GParamSpec * props[PROP_LAST] = { NULL, };
-static gchar msg_stop_projection[] = {
- 0x00, 0x24, /* Length (36 bytes) */
- 0x01, /* MICE Protocol Version */
- 0x02, /* Command STOP_PROJECTION */
+static void
+dump_message (guint8 *msg, gsize length)
+{
+ g_autoptr(GString) line = NULL;
- 0x00, /* Friendly Name TLV */
- 0x00, 0x0A, /* Length (10 bytes) */
- /* GNOME (UTF-16-encoded) */
- 0x47, 0x00, 0x4E, 0x00, 0x4F, 0x00, 0x4D, 0x00, 0x45, 0x00,
+ line = g_string_new ("");
+ /* Dump the buffer. */
+ for (gint i = 0; i < length; i++)
+ {
+ g_string_append_printf (line, "%02x ", msg[i]);
+ if ((i + 1) % 16 == 0)
+ {
+ g_debug ("%s", line->str);
+ g_string_set_size (line, 0);
+ }
+ }
- 0x03, /* Source ID TLV */
- 0x00, 0x10, /* Length (16 bytes) */
- /* Source ID GnomeMICEDisplay (ascii) */
- 0x47, 0x6E, 0x6F, 0x6D, 0x65, 0x4D, 0x49, 0x43, 0x45, 0x44, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79
-};
+ if (line->len)
+ g_debug ("%s", line->str);
+}
static void
nd_cc_sink_get_property (GObject * object,
@@ -289,120 +294,212 @@ parse_received_data(uint8_t * input_buffer, gssize input_size)
castchannel__cast_message__free_unpacked(message, NULL);
}
-gboolean
-comm_client_send (NdCCSink * self,
- GSocketClient * client,
- gchar * remote_address,
- const void * message,
- gssize size,
- GCancellable * cancellable,
- GError * error)
+static gboolean
+accept_certificate (GTlsClientConnection *conn,
+ GTlsCertificate *cert,
+ GTlsCertificateFlags errors,
+ gpointer user_data)
{
- GOutputStream * ostream;
- GInputStream * istream;
- gssize input_size;
- uint8_t * input_buffer = malloc(MAX_MSG_SIZE);
-
- if (self->comm_client_conn == NULL)
- self->comm_client_conn = g_socket_client_connect_to_host (client,
- (gchar *) remote_address,
- 8009,
- // 8010,
- NULL,
- &error);
-
- if (!self->comm_client_conn || error != NULL)
+ g_print ("Certificate would have been rejected ( ");
+ if (errors & G_TLS_CERTIFICATE_UNKNOWN_CA)
+ g_print ("unknown-ca ");
+ if (errors & G_TLS_CERTIFICATE_BAD_IDENTITY)
+ g_print ("bad-identity ");
+ if (errors & G_TLS_CERTIFICATE_NOT_ACTIVATED)
+ g_print ("not-activated ");
+ if (errors & G_TLS_CERTIFICATE_EXPIRED)
+ g_print ("expired ");
+ if (errors & G_TLS_CERTIFICATE_REVOKED)
+ g_print ("revoked ");
+ if (errors & G_TLS_CERTIFICATE_INSECURE)
+ g_print ("insecure ");
+ g_print (") but accepting anyway.\n");
+
+ return TRUE;
+}
+
+static gboolean
+make_connection (NdCCSink * sink,
+ GSocket ** socket,
+ GInputStream ** istream,
+ GOutputStream ** ostream,
+ GError ** error)
+{
+ NdCCSink * self = ND_CC_SINK (sink);
+ GSocketType socket_type;
+ GSocketFamily socket_family;
+ GSocketConnectable * connectable;
+ GIOStream *tls_conn;
+ // GError *err = NULL;
+ // GSocketAddressEnumerator * enumerator;
+
+ // return true if already connected
+ if (*socket != NULL && G_IS_TLS_CONNECTION (self->connection))
+ return TRUE;
+
+ socket_type = G_SOCKET_TYPE_STREAM;
+ socket_family = G_SOCKET_FAMILY_IPV4;
+ *socket = g_socket_new (socket_family, socket_type, G_SOCKET_PROTOCOL_DEFAULT, error);
+ if (*socket == NULL)
{
- if (error != NULL)
- g_warning ("NdCCSink: Failed to write to communication stream: %s", error->message);
+ g_warning ("NdCCSink: Failed to create socket: %s", (*error)->message);
return FALSE;
}
- g_assert (G_IO_STREAM (self->comm_client_conn));
- g_debug ("NdCCSink: Client connection established");
+ // XXX
+ // g_socket_set_timeout (*socket, 10);
- ostream = g_io_stream_get_output_stream (G_IO_STREAM (self->comm_client_conn));
- if (!ostream)
+ connectable = g_network_address_parse (self->remote_address, 8009, error);
+ if (connectable == NULL)
{
- g_warning ("NdCCSink: Could not signal to sink");
+ g_warning ("NdCCSink: Failed to create connectable: %s", (*error)->message);
return FALSE;
}
- size = g_output_stream_write (ostream, message, size, cancellable, &error);
- if (error != NULL)
- {
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
- {
- g_warning ("NdCCSink: Communication client socket send would block");
- return FALSE;
- }
- else
- {
- g_warning ("NdCCSink: Error writing to client socket output: %s", error->message);
- return FALSE;
- }
- }
+ // enumerator = g_socket_connectable_enumerate (connectable);
+ // while (TRUE)
+ // {
+ // *address = g_socket_address_enumerator_next (enumerator, cancellable, error);
+ // if (*address == NULL)
+ // {
+ // g_warning ("NdCCSink: Failed to create address: %s", error->message);
+ // return FALSE;
+ // }
+
+ // if (g_socket_connect (*socket, *address, cancellable, &err))
+ // break;
+
+ // g_message ("Connection to %s failed: %s, trying next", socket_address_to_string (*address),
err->message);
+ // g_clear_error (&err);
+
+ // g_object_unref (*address);
+ // }
+ // g_object_unref (enumerator);
- g_debug ("NdCCSink: Sent %" G_GSSIZE_FORMAT " bytes of data", size);
-
- g_debug ("NdCCSink: Waiting for response from sink");
+ // g_debug ("NdCCSink: Connected to %s", (*address));
+
+ self->connection = G_IO_STREAM (g_socket_connection_factory_create_connection (*socket));
- // get input stream from the connection
- istream = g_io_stream_get_input_stream (G_IO_STREAM (self->comm_client_conn));
- if (!istream)
+ tls_conn = g_tls_client_connection_new (self->connection, connectable, error);
+ if (tls_conn == NULL)
{
- g_warning ("NdCCSink: Could not get input stream from client connection");
+ g_warning ("NdCCSink: Failed to create TLS connection: %s", (*error)->message);
return FALSE;
}
- // read the response from the sink
- input_size = g_input_stream_read (istream, input_buffer, MAX_MSG_SIZE, NULL, &error);
- if (error != NULL)
- {
- g_warning ("NdCCSink: Error reading from client socket input: %s", error->message);
- // return FALSE;
- }
+ g_signal_connect (tls_conn, "accept-certificate", G_CALLBACK (accept_certificate), NULL);
+ g_object_unref (self->connection);
- g_debug("NdCCSink: Received %" G_GSSIZE_FORMAT " bytes of data", input_size);
- // for (int i = 0; i < input_size; i++)
+ self->connection = G_IO_STREAM (tls_conn);
+
+ // see what should be done about cancellable
+ // FIXME: handshake fails
+ // if (!g_tls_connection_handshake (G_TLS_CONNECTION (tls_conn), NULL, error))
// {
- // g_debug ("NdCCSink: Received byte %", input_buffer[i]);
+ // g_warning ("NdCCSink: Failed to handshake: %s", (*error)->message);
+ // return FALSE;
// }
- g_debug("NdCCSink: Received Message: %s", input_buffer);
- parse_received_data(input_buffer, input_size);
+ *istream = g_io_stream_get_input_stream (self->connection);
+ *ostream = g_io_stream_get_output_stream (self->connection);
- free(input_buffer);
+ g_debug ("NdCCSink: Connected to %s", self->remote_address);
return TRUE;
}
-static void
-closed_cb (NdCCSink *sink, CCClient *client)
+gboolean
+tls_send (NdCCSink * sink,
+ uint8_t * message,
+ gssize size,
+ GError * error)
{
- g_autoptr(GError) error = NULL;
+ NdCCSink * self = ND_CC_SINK (sink);
+ GSocket * socket;
+ GInputStream * istream;
+ GOutputStream * ostream;
+ gssize io_bytes;
+ uint8_t buffer[MAX_MSG_SIZE];
- /* Connection was closed, do a clean shutdown*/
- gboolean comm_client_ok = comm_client_send (sink,
- sink->comm_client,
- sink->remote_address,
- msg_stop_projection,
- sizeof (msg_stop_projection),
- NULL,
- error);
+ if (!make_connection (self, &socket, &istream, &ostream, &error))
+ {
+ g_warning ("NdCCSink: Failed to make connection: %s", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
- if (!comm_client_ok || error != NULL)
- {
- if (error != NULL)
- g_warning ("NdCCSink: Failed to send stop projection cmd to client: %s", error->message);
- else
- g_warning ("NdCCSink: Failed to send stop projection cmd to client");
+ g_assert (G_IS_TLS_CONNECTION (self->connection));
+
+ // start sending data
+ g_debug ("Writing data:");
+ dump_message (message, size);
+
+ while (size > 0)
+ {
+ g_socket_condition_check (socket, G_IO_OUT);
+ io_bytes = g_output_stream_write (ostream, message, size, NULL, &error);
- sink->state = ND_SINK_STATE_ERROR;
- g_object_notify (G_OBJECT (sink), "state");
- g_clear_object (&sink->server);
+ if (io_bytes <= 0)
+ {
+ g_warning ("NdCCSink: Failed to write: %s", error->message);
+ g_error_free (error);
+ return FALSE;
}
- nd_cc_sink_sink_stop_stream (ND_SINK (sink));
+
+ g_debug ("NdCCSink: Sent %" G_GSSIZE_FORMAT " bytes", io_bytes);
+
+ size -= io_bytes;
+ }
+
+ // wait for response
+ g_socket_condition_check (socket, G_IO_IN);
+ io_bytes = g_input_stream_read (istream, buffer, MAX_MSG_SIZE, NULL, &error);
+
+ if (io_bytes <= 0)
+ {
+ g_warning ("NdCCSink: Failed to read: %s", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ g_debug ("NdCCSink: Received %" G_GSSIZE_FORMAT " bytes", io_bytes);
+ g_debug ("Received data:");
+ dump_message (buffer, io_bytes);
+
+ g_print ("-------------------------\n"
+ "%.*s"
+ "-------------------------\n",
+ (int)io_bytes, buffer);
+
+ return TRUE;
+}
+
+static void
+closed_cb (NdCCSink *sink, CCClient *client)
+{
+ // g_autoptr(GError) error = NULL;
+
+ // /* Connection was closed, do a clean shutdown*/
+ // gboolean comm_client_ok = comm_client_send (sink,
+ // sink->comm_client,
+ // sink->remote_address,
+ // msg_stop_projection,
+ // sizeof (msg_stop_projection),
+ // NULL,
+ // error);
+
+ // if (!comm_client_ok || error != NULL)
+ // {
+ // if (error != NULL)
+ // g_warning ("NdCCSink: Failed to send stop projection cmd to client: %s", error->message);
+ // else
+ // g_warning ("NdCCSink: Failed to send stop projection cmd to client");
+
+ // sink->state = ND_SINK_STATE_ERROR;
+ // g_object_notify (G_OBJECT (sink), "state");
+ // g_clear_object (&sink->server);
+ // }
+ // nd_cc_sink_sink_stop_stream (ND_SINK (sink));
}
static void
@@ -548,16 +645,10 @@ send_request (NdCCSink *sink, enum MessageType message_type, char * utf8_payload
castchannel__cast_message__pack(&message, 4 + sock_buffer);
g_debug("Sending message to %s:%s", self->remote_address, self->remote_name);
- send_ok = comm_client_send (self,
- self->comm_client,
- self->remote_address,
- sock_buffer,
- packed_size+4,
- NULL,
- error);
-
- // g_debug("Waiting for response");
- // g_io_add_watch(self->comm_client_conn, G_IO_IN | G_IO_HUP, msg_received_cb, self);
+ send_ok = tls_send (self,
+ sock_buffer,
+ packed_size+4,
+ error);
if (!send_ok || error != NULL)
{
@@ -586,6 +677,9 @@ nd_cc_sink_sink_start_stream (NdSink *sink)
// self->state = ND_SINK_STATE_ENSURE_FIREWALL;
// g_object_notify (G_OBJECT (self), "state");
+ self->state = ND_SINK_STATE_WAIT_SOCKET;
+ g_object_notify (G_OBJECT (self), "state");
+
g_debug ("NdCCSink: Attempting connection to Chromecast: %s", self->remote_name);
// send connection request to client
@@ -643,30 +737,30 @@ nd_cc_sink_sink_start_stream (NdSink *sink)
static void
nd_cc_sink_sink_stop_stream_int (NdCCSink *self)
{
- g_autoptr(GError) error;
- gboolean close_ok;
+ // g_autoptr(GError) error;
+ // gboolean close_ok;
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
self->cancellable = g_cancellable_new ();
- /* Close the client connection */
- if (self->comm_client_conn != NULL)
- {
- close_ok = g_io_stream_close (G_IO_STREAM (self->comm_client_conn), NULL, &error);
- if (error != NULL)
- {
- g_warning ("NdCCSink: Error closing communication client connection: %s", error->message);
- }
- if (!close_ok)
- {
- g_warning ("NdCCSink: Communication client connection not closed");
- }
-
- g_clear_object (&self->comm_client_conn);
- g_debug ("NdCCSink: Client connection removed");
- }
+ /* TODO: Close the client connection */
+ // if (self->comm_client_conn != NULL)
+ // {
+ // close_ok = g_io_stream_close (G_IO_STREAM (self->comm_client_conn), NULL, &error);
+ // if (error != NULL)
+ // {
+ // g_warning ("NdCCSink: Error closing communication client connection: %s", error->message);
+ // }
+ // if (!close_ok)
+ // {
+ // g_warning ("NdCCSink: Communication client connection not closed");
+ // }
+
+ // g_clear_object (&self->comm_client_conn);
+ // g_debug ("NdCCSink: Client connection removed");
+ // }
/* Destroy the server that is streaming. */
if (self->server_source_id)
@@ -701,6 +795,7 @@ nd_cc_sink_sink_stop_stream (NdSink *sink)
* NdCCSink public functions
******************************************************************/
+// XXX: no use for client
NdCCSink *
nd_cc_sink_new (GSocketClient *client,
gchar *name,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]