Exemplo n.º 1
0
WebSocketConnection *
cockpit_web_service_create_socket (const gchar **protocols,
                                   const gchar *path,
                                   GIOStream *io_stream,
                                   GHashTable *headers,
                                   GByteArray *input_buffer)
{
  WebSocketConnection *connection;
  const gchar *host = NULL;
  const gchar *protocol = NULL;
  const gchar **origins;
  gchar *allocated = NULL;
  gchar *origin = NULL;
  gchar *defaults[2];
  gboolean secure;
  gchar *url;

  g_return_val_if_fail (path != NULL, NULL);

  if (headers)
    host = g_hash_table_lookup (headers, "Host");
  if (!host)
    host = cockpit_ws_default_host_header;

  /* No headers case for tests */
  if (cockpit_ws_default_protocol_header && !headers &&
      cockpit_conf_string ("WebService", "ProtocolHeader"))
    {
      protocol = cockpit_ws_default_protocol_header;
    }
  else
    {
      protocol = cockpit_web_response_get_protocol (io_stream, headers);
    }

  secure = g_strcmp0 (protocol, "https") == 0;

  url = g_strdup_printf ("%s://%s%s",
                         secure ? "wss" : "ws",
                         host ? host : "localhost",
                         path);

  origins = cockpit_conf_strv ("WebService", "Origins", ' ');
  if (origins == NULL)
    {
      origin = g_strdup_printf ("%s://%s", secure ? "https" : "http", host);
      defaults[0] = origin;
      defaults[1] = NULL;
      origins = (const gchar **)defaults;
    }

  connection = web_socket_server_new_for_stream (url, origins, protocols,
                                                 io_stream, headers, input_buffer);
  g_free (allocated);
  g_free (url);
  g_free (origin);

  return connection;
}
Exemplo n.º 2
0
static gboolean
on_handle_stream_external (CockpitWebServer *server,
                           const gchar *path,
                           GIOStream *io_stream,
                           GHashTable *headers,
                           GByteArray *input,
                           gpointer user_data)
{
  CockpitWebResponse *response;
  gboolean handled = FALSE;
  const gchar *upgrade;
  CockpitCreds *creds;
  const gchar *expected;
  const gchar *query;
  const gchar *segment;
  JsonObject *open = NULL;
  GBytes *bytes;
  guchar *decoded;
  gsize length;
  gsize seglen;

  if (g_str_has_prefix (path, "/cockpit/echosocket"))
    {
      const gchar *protocols[] = { "cockpit1", NULL };
      const gchar *origins[2] = { NULL, NULL };
      WebSocketConnection *ws = NULL;
      gchar *url;

      url = g_strdup_printf ("ws://localhost:%u%s", server_port, path);
      origins[0] = g_strdup_printf ("http://localhost:%u", server_port);

      ws = web_socket_server_new_for_stream (url, (const gchar **)origins,
                                             protocols, io_stream, headers, input);

      g_signal_connect (ws, "message", G_CALLBACK (on_echo_socket_message), NULL);
      g_signal_connect (ws, "close", G_CALLBACK (on_echo_socket_close), NULL);
      return TRUE;
    }

  if (!g_str_has_prefix (path, "/cockpit/channel/"))
    return FALSE;

  /* Remove /cockpit/channel/ part */
  segment = path + 17;

  if (service)
    {
      creds = cockpit_web_service_get_creds (service);
      g_return_val_if_fail (creds != NULL, FALSE);

      expected = cockpit_creds_get_csrf_token (creds);
      g_return_val_if_fail (expected != NULL, FALSE);

      /* The end of the token */
      query = strchr (segment, '?');
      if (!query)
        query = segment + strlen (segment);

      /* No such path is valid */
      seglen = query - segment;
      if (strlen(expected) == seglen && memcmp (expected, segment, seglen) == 0)
        {
          decoded = g_base64_decode (query, &length);
          if (decoded)
            {
              bytes = g_bytes_new_take (decoded, length);
              if (!cockpit_transport_parse_command (bytes, NULL, NULL, &open))
                {
                  open = NULL;
                  g_message ("invalid external channel query");
                }
              g_bytes_unref (bytes);
            }
        }

      if (open)
        {
          upgrade = g_hash_table_lookup (headers, "Upgrade");
          if (upgrade && g_ascii_strcasecmp (upgrade, "websocket") == 0)
            {
              cockpit_channel_socket_open (service, open, path, io_stream, headers, input);
              handled = TRUE;
            }
          else
            {
              response = cockpit_web_response_new (io_stream, path, NULL, headers);
              cockpit_channel_response_open (service, headers, response, open);
              g_object_unref (response);
              handled = TRUE;
            }

          json_object_unref (open);
        }
    }

  return handled;
}