static void on_socket_close (WebSocketConnection *connection, CockpitChannelSocket *chock) { const gchar *problem = NULL; GBytes *payload; gushort code; code = web_socket_connection_get_close_code (chock->socket); if (code == WEB_SOCKET_CLOSE_NORMAL) { payload = cockpit_transport_build_control ("command", "done", "channel", chock->channel, NULL); cockpit_transport_send (chock->transport, NULL, payload); g_bytes_unref (payload); } else { problem = web_socket_connection_get_close_data (chock->socket); if (problem == NULL) problem = "disconnected"; } payload = cockpit_transport_build_control ("command", "close", "channel", chock->channel, "problem", problem, NULL); cockpit_transport_send (chock->transport, NULL, payload); g_bytes_unref (payload); cockpit_channel_socket_close (chock, problem); }
static void on_web_socket_noauth (WebSocketConnection *connection, gpointer data) { GBytes *payload; GBytes *prefix; g_debug ("closing unauthenticated web socket"); payload = cockpit_transport_build_control ("command", "init", "problem", "no-session", NULL); prefix = g_bytes_new_static ("\n", 1); web_socket_connection_send (connection, WEB_SOCKET_DATA_TEXT, prefix, payload); web_socket_connection_close (connection, WEB_SOCKET_CLOSE_GOING_AWAY, "no-session"); g_bytes_unref (prefix); g_bytes_unref (payload); }
static void inbound_protocol_error (CockpitWebService *self, WebSocketConnection *connection, const gchar *problem) { GBytes *payload; if (problem == NULL) problem = "protocol-error"; if (web_socket_connection_get_ready_state (connection) == WEB_SOCKET_STATE_OPEN) { payload = cockpit_transport_build_control ("command", "close", "problem", problem, NULL); web_socket_connection_send (connection, WEB_SOCKET_DATA_TEXT, self->control_prefix, payload); g_bytes_unref (payload); web_socket_connection_close (connection, WEB_SOCKET_CLOSE_SERVER_ERROR, problem); } }
static gboolean on_ping_time (gpointer user_data) { CockpitWebService *self = user_data; WebSocketConnection *connection; GHashTableIter iter; GBytes *payload; payload = cockpit_transport_build_control ("command", "ping", NULL); g_hash_table_iter_init (&iter, self->sockets.by_connection); while (g_hash_table_iter_next (&iter, (gpointer *)&connection, NULL)) { if (web_socket_connection_get_ready_state (connection) == WEB_SOCKET_STATE_OPEN) web_socket_connection_send (connection, WEB_SOCKET_DATA_TEXT, self->control_prefix, payload); } g_bytes_unref (payload); return TRUE; }
static gboolean on_web_socket_closing (WebSocketConnection *connection, CockpitWebService *self) { CockpitSocket *socket; GHashTable *snapshot; GHashTableIter iter; const gchar *channel; GBytes *payload; g_debug ("web socket closing"); if (self->sent_done) return TRUE; /* Close any channels that were opened by this web socket */ snapshot = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); socket = cockpit_socket_lookup_by_connection (&self->sockets, connection); if (socket) { g_hash_table_iter_init (&iter, socket->channels); while (g_hash_table_iter_next (&iter, (gpointer *)&channel, NULL)) { g_hash_table_add (snapshot, g_strdup (channel)); } } g_hash_table_iter_init (&iter, snapshot); while (g_hash_table_iter_next (&iter, (gpointer *)&channel, NULL)) { payload = cockpit_transport_build_control ("command", "close", "channel", channel, "problem", "disconnected", NULL); cockpit_transport_send (self->transport, NULL, payload); g_bytes_unref (payload); } g_hash_table_destroy (snapshot); return TRUE; }
static void send_socket_hints (CockpitWebService *self, const gchar *name, const gchar *value) { CockpitSocket *socket; GHashTableIter iter; GBytes *payload; payload = cockpit_transport_build_control ("command", "hint", name, value, NULL); g_hash_table_iter_init (&iter, self->sockets.by_connection); while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&socket)) { if (web_socket_connection_get_ready_state (socket->connection) == WEB_SOCKET_STATE_OPEN) { web_socket_connection_send (socket->connection, WEB_SOCKET_DATA_TEXT, self->control_prefix, payload); } } g_bytes_unref (payload); }
static gboolean process_transport_authorize (CockpitWebService *self, CockpitTransport *transport, JsonObject *options) { const gchar *cookie = NULL; GBytes *payload; char *type = NULL; char *alloc = NULL; const char *response = NULL; const gchar *challenge; const gchar *password; const gchar *host; GBytes *data; if (!cockpit_json_get_string (options, "challenge", NULL, &challenge) || !cockpit_json_get_string (options, "cookie", NULL, &cookie) || !cockpit_json_get_string (options, "host", NULL, &host)) { g_warning ("received invalid authorize command"); return FALSE; } if (!challenge || !cookie) { g_message ("unsupported or unknown authorize command"); return FALSE; } if (!cockpit_authorize_type (challenge, &type)) { g_message ("received invalid authorize challenge command"); } else if (g_str_equal (type, "plain1") || g_str_equal (type, "crypt1") || g_str_equal (type, "basic")) { data = cockpit_creds_get_password (self->creds); if (!data) { g_debug ("%s: received \"authorize\" %s \"challenge\", but no password", host, type); } else if (!g_str_equal ("basic", type) && !authorize_check_user (self->creds, challenge)) { g_debug ("received \"authorize\" %s \"challenge\", but for wrong user", type); } else { password = g_bytes_get_data (data, NULL); if (g_str_equal (type, "crypt1")) { alloc = cockpit_compat_reply_crypt1 (challenge, password); if (alloc) response = alloc; else g_message ("failed to \"authorize\" crypt1 \"challenge\""); } else if (g_str_equal (type, "basic")) { response = cockpit_authorize_build_basic (cockpit_creds_get_user (self->creds), password); } else { response = password; } } } /* Tell the frontend that we're reauthorizing */ if (self->init_received) { self->credential_requests++; send_socket_hints (self, "credential", "request"); } if (cookie && !self->sent_done) { payload = cockpit_transport_build_control ("command", "authorize", "cookie", cookie, "response", response ? response : "", "host", host, NULL); cockpit_transport_send (transport, NULL, payload); g_bytes_unref (payload); } free (type); free (alloc); return TRUE; }