Ejemplo n.º 1
0
gboolean
cockpit_handler_index (CockpitWebServer *server,
                       CockpitWebServerRequestType reqtype,
                       const gchar *path,
                       GHashTable *headers,
                       GBytes *input,
                       CockpitWebResponse *response,
                       CockpitHandlerData *ws)
{
  CockpitWebService *service;

  if (reqtype != COCKPIT_WEB_SERVER_REQUEST_GET)
    return FALSE;

  /*
   * In the future this code path should also be taken for GSSAPI
   * single-sign-on authentication, where the user never sees a login
   * screen.
   */

  service = cockpit_auth_check_cookie (ws->auth, headers);
  if (service)
    {
      /* Already logged in, lookup modules and return full environment */
      cockpit_web_service_modules (service, "localhost", on_index_modules,
                                   g_object_ref (response));
    }
  else
    {
      /* Not logged in, include half-baked environment */
      send_index_response (response, NULL, NULL);
    }

  return TRUE;
}
Ejemplo n.º 2
0
gboolean
cockpit_handler_deauthorize (CockpitWebServer *server,
                             CockpitWebServerRequestType reqtype,
                             const gchar *path,
                             GHashTable *headers,
                             GBytes *input,
                             CockpitWebResponse *response,
                             CockpitHandlerData *ws)
{
  CockpitWebService *service;
  CockpitCreds *creds;
  const gchar *body;
  GBytes *bytes;

  service = cockpit_auth_check_cookie (ws->auth, headers);
  if (!service)
    {
      cockpit_web_response_error (response, 401, NULL, "Unauthorized");
      return TRUE;
    }

  /* Poison the creds, so they no longer work for new reauthorization */
  creds = cockpit_web_service_get_creds (service);
  cockpit_creds_poison (creds);
  g_object_unref (service);

  body ="<html><head><title>Deauthorized</title></head>"
    "<body>Deauthorized</body></html>";

  bytes = g_bytes_new_static (body, strlen (body));
  cockpit_web_response_content (response, NULL, bytes, NULL);
  g_bytes_unref (bytes);
  return TRUE;
}
Ejemplo n.º 3
0
/* Called by @server when handling HTTP requests to /socket - runs in a separate
 * thread dedicated to the request so it may do blocking I/O
 */
gboolean
cockpit_handler_socket (CockpitWebServer *server,
                        CockpitWebServerRequestType reqtype,
                        const gchar *path,
                        GIOStream *io_stream,
                        GHashTable *headers,
                        GByteArray *input,
                        guint in_length,
                        CockpitHandlerData *ws)
{
  CockpitWebService *service;

  if (!g_str_equal (path, "/socket"))
    return FALSE;

  service = cockpit_auth_check_cookie (ws->auth, headers);
  if (service)
    {
      cockpit_web_service_socket (service, io_stream, headers, input);
      g_object_unref (service);
    }
  else
    {
      cockpit_web_service_noauth (io_stream, headers, input);
    }

  return TRUE;
}
Ejemplo n.º 4
0
gboolean
cockpit_handler_login (CockpitWebServer *server,
                       const gchar *path,
                       GHashTable *headers,
                       CockpitWebResponse *response,
                       CockpitHandlerData *ws)
{
  CockpitWebService *service;
  CockpitCreds *creds;
  gchar *remote_peer = NULL;
  GHashTable *out_headers;
  GIOStream *io_stream;

  service = cockpit_auth_check_cookie (ws->auth, headers);
  if (service == NULL)
    {
      io_stream = cockpit_web_response_get_stream (response);
      remote_peer = get_remote_address (io_stream);
      cockpit_auth_login_async (ws->auth, headers, remote_peer, on_login_complete,
                                g_object_ref (response));
      g_free (remote_peer);
    }
  else
    {
      out_headers = cockpit_web_server_new_table ();
      creds = cockpit_web_service_get_creds (service);
      send_login_response (response, creds, out_headers);
      g_hash_table_unref (out_headers);
      g_object_unref (service);
    }

  /* no response yet */
  return TRUE;
}
Ejemplo n.º 5
0
gboolean
cockpit_handler_resource (CockpitWebServer *server,
                          const gchar *path,
                          GHashTable *headers,
                          CockpitWebResponse *response,
                          CockpitHandlerData *ws)
{
  CockpitWebService *service;

  if (g_str_has_prefix (path, "/cockpit/static/"))
    {
      cockpit_web_response_file (response, path + 16, TRUE, ws->static_roots);
      return TRUE;
    }

  service = cockpit_auth_check_cookie (ws->auth, headers);
  if (service)
    {
      cockpit_web_service_resource (service, headers, response);
      g_object_unref (service);
    }
  else if (g_str_equal (path, "/") || g_str_has_suffix (path, ".html"))
    {
      send_login_html (response, ws);
    }
  else
    {
      cockpit_web_response_error (response, 401, NULL, NULL);
    }

  return TRUE;
}
Ejemplo n.º 6
0
gboolean
cockpit_handler_default (CockpitWebServer *server,
                         const gchar *path,
                         GHashTable *headers,
                         CockpitWebResponse *response,
                         CockpitHandlerData *data)
{
  CockpitWebService *service;
  const gchar *remainder = NULL;
  gboolean resource;

  path = cockpit_web_response_get_path (response);
  g_return_val_if_fail (path != NULL, FALSE);

  resource = g_str_has_prefix (path, "/cockpit/") ||
             g_str_has_prefix (path, "/cockpit+") ||
             g_str_equal (path, "/cockpit");

  // Check for auth
  service = cockpit_auth_check_cookie (data->auth, path, headers);

  /* Stuff in /cockpit or /cockpit+xxx */
  if (resource)
    {
      cockpit_web_response_skip_path (response);
      remainder = cockpit_web_response_get_path (response);

      if (!remainder)
        {
          cockpit_web_response_error (response, 404, NULL, NULL);
          return TRUE;
        }
      else if (g_str_has_prefix (remainder, "/static/"))
        {
          cockpit_branding_serve (service, response, path, remainder + 8,
                                  data->os_release, data->branding_roots);
          return TRUE;
        }
    }

  if (resource)
    {
      if (g_str_equal (remainder, "/login"))
        {
          handle_login (data, service, path, headers, response);
        }
      else
        {
          handle_resource (data, service, path, headers, response);
        }
    }
  else
    {
      handle_shell (data, service, path, headers, response);
    }

  return TRUE;
}
Ejemplo n.º 7
0
gboolean
cockpit_handler_login (CockpitWebServer *server,
                       CockpitWebServerRequestType reqtype,
                       const gchar *path,
                       GHashTable *headers,
                       GBytes *input,
                       CockpitWebResponse *response,
                       CockpitHandlerData *ws)
{
  CockpitWebService *service;
  gchar *remote_peer = NULL;
  GIOStream *io_stream;
  LoginResponse *lr;

  lr = g_new0 (LoginResponse, 1);
  lr->response = g_object_ref (response);
  lr->headers = cockpit_web_server_new_table ();

  if (reqtype == COCKPIT_WEB_SERVER_REQUEST_GET)
    {
      service = cockpit_auth_check_cookie (ws->auth, headers);
      if (service == NULL)
        {
          cockpit_web_response_error (response, 401, NULL, NULL);
          login_response_free (lr);
        }
      else
        {
          cockpit_web_service_modules (service, "localhost", on_login_modules, lr);
          g_object_unref (service);
          /* no response yet */
        }
    }
  else if (reqtype == COCKPIT_WEB_SERVER_REQUEST_POST)
    {
      io_stream = cockpit_web_response_get_stream (response);
      remote_peer = get_remote_address (io_stream);
      cockpit_auth_login_async (ws->auth, headers, input, remote_peer,
                                on_login_complete, lr);
      g_free (remote_peer);
      /* no response yet */
    }

  return TRUE;
}
Ejemplo n.º 8
0
/* Called by @server when handling HTTP requests to /cockpit/socket */
gboolean
cockpit_handler_socket (CockpitWebServer *server,
                        const gchar *original_path,
                        const gchar *path,
                        const gchar *method,
                        GIOStream *io_stream,
                        GHashTable *headers,
                        GByteArray *input,
                        CockpitHandlerData *ws)
{
  CockpitWebService *service = NULL;
  const gchar *segment = NULL;

  /*
   * Socket requests should come in on /cockpit/socket or /cockpit+app/socket.
   * However older javascript may connect on /socket, so we continue to support that.
   */

  if (path && path[0])
    segment = strchr (path + 1, '/');
  if (!segment)
    segment = path;

  if (!segment || !g_str_equal (segment, "/socket"))
    return FALSE;

  /* don't support HEAD on a socket, it makes little sense */
  if (g_strcmp0 (method, "GET") != 0)
      return FALSE;

  if (headers)
    service = cockpit_auth_check_cookie (ws->auth, path, headers);
  if (service)
    {
      cockpit_web_service_socket (service, path, io_stream, headers, input);
      g_object_unref (service);
    }
  else
    {
      handle_noauth_socket (io_stream, path, headers, input);
    }

  return TRUE;
}
Ejemplo n.º 9
0
gboolean
cockpit_handler_resource (CockpitWebService *server,
                          CockpitWebServerRequestType reqtype,
                          const gchar *path,
                          GHashTable *headers,
                          GBytes *input,
                          CockpitWebResponse *response,
                          CockpitHandlerData *ws)
{
  CockpitWebService *service;

  service = cockpit_auth_check_cookie (ws->auth, headers);
  if (service)
    {
      cockpit_web_service_resource (service, response);
      g_object_unref (service);
    }
  else
    {
      cockpit_web_response_error (response, 401, NULL, NULL);
    }

  return TRUE;
}
Ejemplo n.º 10
0
/* Called by @server when handling HTTP requests to /socket - runs in a separate
 * thread dedicated to the request so it may do blocking I/O
 */
gboolean
cockpit_handler_socket (CockpitWebServer *server,
                        const gchar *path,
                        GIOStream *io_stream,
                        GHashTable *headers,
                        GByteArray *input,
                        guint in_length,
                        CockpitHandlerData *ws)
{
  CockpitWebService *service;
  const gchar *query = NULL;

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

  if (path[7] == '?')
    query = path + 8;
  else if (path[7] != '\0')
    return FALSE;

  service = cockpit_auth_check_cookie (ws->auth, headers);
  if (service)
    {
      if (query)
        cockpit_web_service_sideband (service, query, io_stream, headers, input);
      else
        cockpit_web_service_socket (service, io_stream, headers, input);
      g_object_unref (service);
    }
  else
    {
      cockpit_web_service_noauth (io_stream, headers, input);
    }

  return TRUE;
}
Ejemplo n.º 11
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;
}