Exemplo n.º 1
0
static void
respond_with_error (const gchar *original_path,
                    const gchar *path,
                    GIOStream *io_stream,
                    GHashTable *headers,
                    guint status,
                    const gchar *message)
{
  CockpitWebResponse *response;

  response = cockpit_web_response_new (io_stream, original_path, path, NULL, headers);
  cockpit_web_response_error (response, status, NULL, "%s", message);
  g_object_unref (response);
}
static void
respond_with_error (const gchar *original_path,
                    const gchar *path,
                    GIOStream *io_stream,
                    gboolean for_tls_proxy,
                    GHashTable *headers,
                    guint status,
                    const gchar *message)
{
  CockpitWebResponse *response;

  response = cockpit_web_response_new (io_stream, original_path, path, NULL, headers,
                                       for_tls_proxy ? COCKPIT_WEB_RESPONSE_FOR_TLS_PROXY : COCKPIT_WEB_RESPONSE_NONE);
  cockpit_web_response_error (response, status, NULL, "%s", message);
  g_object_unref (response);
}
Exemplo n.º 3
0
static void
process_delayed_reply (CockpitRequest *request,
                       const gchar *path,
                       GHashTable *headers)
{
  CockpitWebResponse *response;
  const gchar *host;
  const gchar *body;
  GBytes *bytes;
  gsize length;
  gchar *url;

  g_assert (request->delayed_reply > 299);

  response = cockpit_web_response_new (request->io, NULL, NULL, headers);
  g_signal_connect_data (response, "done", G_CALLBACK (on_web_response_done),
                         g_object_ref (request->web_server), (GClosureNotify)g_object_unref, 0);

  if (request->delayed_reply == 301)
    {
      body = "<html><head><title>Moved</title></head>"
        "<body>Please use TLS</body></html>";
      host = g_hash_table_lookup (headers, "Host");
      url = g_strdup_printf ("https://%s%s",
                             host != NULL ? host : "", path);
      length = strlen (body);
      cockpit_web_response_headers (response, 301, "Moved Permanently", length,
                                    "Content-Type", "text/html",
                                    "Location", url,
                                    NULL);
      g_free (url);
      bytes = g_bytes_new_static (body, length);
      if (cockpit_web_response_queue (response, bytes))
        cockpit_web_response_complete (response);
      g_bytes_unref (bytes);
    }
  else
    {
      cockpit_web_response_error (response, request->delayed_reply, NULL, NULL);
    }

  g_object_unref (response);
}
Exemplo n.º 4
0
static gboolean
cockpit_web_server_default_handle_stream (CockpitWebServer *self,
                                          const gchar *path,
                                          GIOStream *io_stream,
                                          GHashTable *headers,
                                          GByteArray *input,
                                          guint in_length)
{
  CockpitWebResponse *response;
  gboolean claimed = FALSE;
  GQuark detail;
  gchar *pos;
  gchar bak;

  /* Yes, we happen to know that we can modify this string safely. */
  pos = strchr (path, '?');
  if (pos != NULL)
    {
      *pos = '\0';
      pos++;
    }

  /* TODO: Correct HTTP version for response */
  response = cockpit_web_response_new (io_stream, path, pos, headers);
  g_signal_connect_data (response, "done", G_CALLBACK (on_web_response_done),
                         g_object_ref (self), (GClosureNotify)g_object_unref, 0);

  /*
   * If the path has more than one component, then we search
   * for handlers registered under the detail like this:
   *
   *   /component/
   *
   * Otherwise we search for handlers registered under detail
   * of the entire path:
   *
   *  /component
   */

  /* Temporarily null terminate string after first component */
  pos = NULL;
  if (path[0] != '\0')
    {
      pos = strchr (path + 1, '/');
      if (pos != NULL)
        {
          pos++;
          bak = *pos;
          *pos = '\0';
        }
    }
  detail = g_quark_try_string (path);
  if (pos != NULL)
    *pos = bak;

  /* See if we have any takers... */
  g_signal_emit (self,
                 sig_handle_resource, detail,
                 path,
                 headers,
                 response,
                 &claimed);

  /* TODO: Here is where we would plug keep-alive into respnse */
  g_object_unref (response);

  return claimed;
}
Exemplo n.º 5
0
gboolean
cockpit_handler_external (CockpitWebServer *server,
                          const gchar *original_path,
                          const gchar *path,
                          GIOStream *io_stream,
                          GHashTable *headers,
                          GByteArray *input,
                          CockpitHandlerData *ws)
{
  CockpitWebResponse *response = NULL;
  CockpitWebService *service = NULL;
  const gchar *segment = NULL;
  JsonObject *open = NULL;
  const gchar *query = NULL;
  CockpitCreds *creds;
  const gchar *expected;
  const gchar *upgrade;
  guchar *decoded;
  GBytes *bytes;
  gsize length;
  gsize seglen;

  /* The path must start with /cockpit+xxx/channel/csrftoken? or similar */
  if (path && path[0])
    segment = strchr (path + 1, '/');
  if (!segment)
    return FALSE;
  if (!g_str_has_prefix (segment, "/channel/"))
    return FALSE;
  segment += 9;

  /* Make sure we are authenticated, otherwise 404 */
  service = cockpit_auth_check_cookie (ws->auth, path, headers);
  if (!service)
    return FALSE;

  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)
    {
      seglen = query - segment;
      query += 1;
    }
  else
    {
      seglen = strlen (segment);
      query = "";
    }

  /* No such path is valid */
  if (strlen (expected) != seglen || memcmp (expected, segment, seglen) != 0)
    {
      g_message ("invalid csrf token");
      return FALSE;
    }

  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)
    {
      response = cockpit_web_response_new (io_stream, original_path, path, NULL, headers);
      cockpit_web_response_error (response, 400, NULL, NULL);
      g_object_unref (response);
    }
  else
    {
      upgrade = g_hash_table_lookup (headers, "Upgrade");
      if (upgrade && g_ascii_strcasecmp (upgrade, "websocket") == 0)
        {
          cockpit_channel_socket_open (service, open, original_path, path, io_stream, headers, input);
        }
      else
        {
          response = cockpit_web_response_new (io_stream, original_path, path, NULL, headers);
          cockpit_channel_response_open (service, headers, response, open);
          g_object_unref (response);
        }
      json_object_unref (open);
    }

  g_object_unref (service);

  return TRUE;
}
Exemplo n.º 6
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;
}