Exemple #1
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;
}
Exemple #2
0
static void
handle_login (CockpitHandlerData *data,
              CockpitWebService *service,
              const gchar *path,
              GHashTable *headers,
              CockpitWebResponse *response)
{
  GHashTable *out_headers;
  GIOStream *io_stream;
  CockpitCreds *creds;
  JsonObject *creds_json = NULL;

  if (service)
    {
      out_headers = cockpit_web_server_new_table ();
      creds = cockpit_web_service_get_creds (service);
      creds_json = cockpit_creds_to_json (creds);
      send_login_response (response, creds_json, out_headers);
      g_hash_table_unref (out_headers);
      json_object_unref (creds_json);
      return;
    }

  io_stream = cockpit_web_response_get_stream (response);
  cockpit_auth_login_async (data->auth, path,io_stream, headers,
                            on_login_complete, g_object_ref (response));
}
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;
}
static void
on_login_complete (GObject *object,
                   GAsyncResult *result,
                   gpointer user_data)
{
  CockpitWebResponse *response = user_data;
  GError *error = NULL;
  CockpitWebService *service;
  CockpitAuthFlags flags = 0;
  CockpitCreds *creds;
  GHashTable *headers;
  GIOStream *io_stream;

  io_stream = cockpit_web_response_get_stream (response);
  if (G_IS_SOCKET_CONNECTION (io_stream))
    flags |= COCKPIT_AUTH_COOKIE_INSECURE;

  headers = cockpit_web_server_new_table ();
  service = cockpit_auth_login_finish (COCKPIT_AUTH (object), result, flags, headers, &error);

  if (error)
    {
      cockpit_web_response_gerror (response, headers, error);
      g_error_free (error);
    }
  else
    {
      creds = cockpit_web_service_get_creds (service);
      send_login_response (response, creds, headers);
      g_object_unref (service);
    }

  g_hash_table_unref (headers);
  g_object_unref (response);
}
Exemple #5
0
static void
handle_login (CockpitHandlerData *data,
              CockpitWebService *service,
              const gchar *path,
              GHashTable *headers,
              CockpitWebResponse *response)
{
  GHashTable *out_headers;
  gchar *remote_peer = NULL;
  GIOStream *io_stream;
  CockpitCreds *creds;

  if (service)
    {
      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);
    }
  else
    {
      io_stream = cockpit_web_response_get_stream (response);
      remote_peer = get_remote_address (io_stream);
      cockpit_auth_login_async (data->auth, path, headers, remote_peer,
                                on_login_complete, g_object_ref (response));
      g_free (remote_peer);
    }
}
static void
cockpit_channel_inject_perform (CockpitChannelInject *inject,
                                CockpitWebResponse *response,
                                CockpitTransport *transport)
{
  static const gchar *marker = "<head>";
  CockpitWebFilter *filter;
  CockpitCreds *creds;
  const gchar *application;
  const gchar *checksum;
  const gchar *host;
  GString *str;
  GBytes *base;

  str = g_string_new ("");

  if (!inject->service)
    return;

  creds = cockpit_web_service_get_creds (inject->service);
  application = cockpit_creds_get_application (creds);

  checksum = cockpit_web_service_get_checksum (inject->service, transport);
  if (checksum)
    {
      g_string_printf (str, "\n    <base href=\"/%s/$%s%s\">", application, checksum, inject->base_path);
    }
  else
    {
      host = cockpit_web_service_get_host (inject->service, transport);
      g_string_printf (str, "\n    <base href=\"/%s/@%s%s\">", application, host, inject->base_path);
    }

  base = g_string_free_to_bytes (str);
  filter = cockpit_web_inject_new (marker, base, 1);
  g_bytes_unref (base);

  cockpit_web_response_add_filter (response, filter);
  g_object_unref (filter);
}
static gboolean
redirect_to_checksum_path (CockpitWebService *service,
                           CockpitWebResponse *response,
                           const gchar *checksum,
                           const gchar *path)
{
  CockpitCreds *creds;
  gchar *location;
  const gchar *body;
  GBytes *bytes;
  gboolean ret;
  gsize length;

  creds = cockpit_web_service_get_creds (service);
  location = g_strdup_printf ("/%s/$%s%s",
                              cockpit_creds_get_application (creds),
                              checksum, path);

  body = "<html><head><title>Temporary redirect</title></head>"
         "<body>Access via checksum</body></html>";

  length = strlen (body);
  cockpit_web_response_headers (response, 307, "Temporary Redirect", length,
                                "Content-Type", "text/html",
                                "Location", location,
                                NULL);
  g_free (location);

  bytes = g_bytes_new_static (body, length);
  ret = cockpit_web_response_queue (response, bytes);
  if (ret)
    cockpit_web_response_complete (response);
  g_bytes_unref (bytes);

  return ret;
}
Exemple #8
0
static GBytes *
build_environment (CockpitWebService *service,
                   JsonObject *modules)
{
  const gchar *user;
  CockpitCreds *creds;
  JsonObject *env;
  JsonObject *localhost;
  JsonObject *languages;
  JsonObject *language;
  struct passwd *pwd;
  gchar *hostname;
  GBytes *bytes;
  guint n;

  const struct {
    const gchar *name;
    const gchar *code;
  } supported_languages[] = {
    { NC_("display-language", "English"), "" },
    { NC_("display-language", "Danish"),  "da" },
    { NC_("display-language", "German"),  "de" },
  };

  env = json_object_new ();
  if (service)
    {
      creds = cockpit_web_service_get_creds (service);
      user = cockpit_creds_get_user (creds);
      json_object_set_string_member (env, "user", user);
      pwd = cockpit_getpwnam_a (user, NULL);
      if (pwd)
        {
          json_object_set_string_member (env, "name", pwd->pw_gecos);
          free (pwd);
        }
    }

  localhost = json_object_new ();

  /* This awkwardly takes the localhost reference */
  json_object_set_object_member (env, "localhost", localhost);

  hostname = g_malloc0 (HOST_NAME_MAX + 1);
  gethostname (hostname, HOST_NAME_MAX);
  hostname[HOST_NAME_MAX] = '\0';

  json_object_set_string_member (env, "hostname", hostname);

  /* Only include version info if logged in */
  if (service)
    {
      json_object_set_string_member (localhost, "version", PACKAGE_VERSION);
      json_object_set_string_member (localhost, "build_info", COCKPIT_BUILD_INFO);
    }

  languages = json_object_new ();

  /* This awkwardly takes the languages reference */
  json_object_set_object_member (localhost, "languages", languages);

  for (n = 0; n < G_N_ELEMENTS (supported_languages); n++)
    {
      language = json_object_new ();
      json_object_set_object_member (languages, supported_languages[n].code, language);
      json_object_set_string_member (language, "name", supported_languages[n].name);
    }

  if (modules)
    json_object_set_object_member (localhost, "modules", json_object_ref (modules));

  bytes = cockpit_json_write_bytes (env);
  json_object_unref (env);

  return bytes;
}
Exemple #9
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;
}
Exemple #10
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;
}