static void send_login_html (CockpitWebResponse *response, CockpitHandlerData *ws) { static const gchar *marker = "<head>"; CockpitWebFilter *filter; GBytes *environment; GError *error = NULL; GBytes *bytes; GBytes *url_bytes = NULL; CockpitWebFilter *filter2 = NULL; const gchar *url_root = NULL; gchar *base; environment = build_environment (ws->os_release); filter = cockpit_web_inject_new (marker, environment, 1); g_bytes_unref (environment); cockpit_web_response_add_filter (response, filter); g_object_unref (filter); url_root = cockpit_web_response_get_url_root (response); if (url_root) base = g_strdup_printf ("<base href=\"%s/\">", url_root); else base = g_strdup ("<base href=\"/\">"); url_bytes = g_bytes_new_take (base, strlen(base)); filter2 = cockpit_web_inject_new (marker, url_bytes, 1); g_bytes_unref (url_bytes); cockpit_web_response_add_filter (response, filter2); g_object_unref (filter2); cockpit_web_response_set_cache_type (response, COCKPIT_WEB_RESPONSE_NO_CACHE); bytes = cockpit_web_response_negotiation (ws->login_html, NULL, NULL, NULL, &error); if (error) { g_message ("%s", error->message); cockpit_web_response_error (response, 500, NULL, NULL); g_error_free (error); } else if (!bytes) { cockpit_web_response_error (response, 404, NULL, NULL); } else { /* The login Content-Security-Policy allows the page to have inline <script> and <style> tags. */ cockpit_web_response_headers (response, 200, "OK", -1, "Content-Security-Policy", "default-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss:", NULL); if (cockpit_web_response_queue (response, bytes)) cockpit_web_response_complete (response); g_bytes_unref (bytes); } }
static gboolean on_handle_resource (CockpitWebServer *server, const gchar *path, GHashTable *headers, CockpitWebResponse *response, gpointer user_data) { gchar **parts; gchar *rebuilt; g_assert (g_str_has_prefix (path, "/pkg")); /* TODO: This needs a better implementation later, when the tests aren't all broken */ parts = g_strsplit (path, "/", -1); if (g_strcmp0 (parts[2], "system") == 0) { g_free (parts[2]); parts[2] = g_strdup ("systemd"); } rebuilt = g_strjoinv ("/", parts); inject_address (response, "bus_address", bus_address); inject_address (response, "direct_address", direct_address); cockpit_web_response_set_cache_type (response, COCKPIT_WEB_RESPONSE_NO_CACHE); cockpit_web_response_file (response, rebuilt, cockpit_web_server_get_document_roots (server)); g_strfreev (parts); g_free (rebuilt); return TRUE; }
static gboolean on_handle_source (CockpitWebServer *server, const gchar *path, GHashTable *headers, CockpitWebResponse *response, gpointer user_data) { cockpit_web_response_set_cache_type (response, COCKPIT_WEB_RESPONSE_NO_CACHE); inject_address (response, "bus_address", bus_address); inject_address (response, "direct_address", direct_address); cockpit_web_response_file (response, path, cockpit_web_server_get_document_roots (server)); return TRUE; }
static void on_login_complete (GObject *object, GAsyncResult *result, gpointer user_data) { CockpitWebResponse *response = user_data; GError *error = NULL; JsonObject *response_data = NULL; GHashTable *headers; GIOStream *io_stream; GBytes *content; io_stream = cockpit_web_response_get_stream (response); headers = cockpit_web_server_new_table (); response_data = cockpit_auth_login_finish (COCKPIT_AUTH (object), result, io_stream, headers, &error); /* Never cache a login response */ cockpit_web_response_set_cache_type (response, COCKPIT_WEB_RESPONSE_NO_CACHE); if (error) { if (response_data) { g_hash_table_insert (headers, g_strdup ("Content-Type"), g_strdup ("application/json")); content = cockpit_json_write_bytes (response_data); cockpit_web_response_headers_full (response, 401, "Authentication required", -1, headers); cockpit_web_response_queue (response, content); cockpit_web_response_complete (response); g_bytes_unref (content); } else { cockpit_web_response_gerror (response, headers, error); } g_error_free (error); } else { send_login_response (response, response_data, headers); } if (response_data) json_object_unref (response_data); g_hash_table_unref (headers); g_object_unref (response); }
static gboolean on_handle_resource (CockpitWebServer *server, const gchar *path, GHashTable *headers, CockpitWebResponse *response, gpointer user_data) { gchar **parts; g_assert (g_str_has_prefix (path, "/pkg")); cockpit_web_response_set_cache_type (response, COCKPIT_WEB_RESPONSE_NO_CACHE); parts = g_strsplit (path, "/", -1); if (g_strcmp0 (parts[2], "manifests.js") == 0 && !parts[3]) handle_manifests_js (response); else if (g_strcmp0 (parts[2], "manifests.json") == 0 && !parts[3]) handle_manifests_json (response); else handle_package_file (server, response, parts); g_strfreev (parts); return TRUE; }
void cockpit_channel_response_serve (CockpitWebService *service, GHashTable *in_headers, CockpitWebResponse *response, const gchar *where, const gchar *path) { CockpitChannelResponse *chesp = NULL; CockpitTransport *transport = NULL; CockpitCacheType cache_type = COCKPIT_WEB_RESPONSE_CACHE_PRIVATE; const gchar *host = NULL; const gchar *pragma; gchar *quoted_etag = NULL; GHashTable *out_headers = NULL; gchar *val = NULL; gboolean handled = FALSE; GHashTableIter iter; const gchar *checksum; JsonObject *object = NULL; JsonObject *heads; gchar *channel = NULL; gchar *language = NULL; gpointer key; gpointer value; g_return_if_fail (COCKPIT_IS_WEB_SERVICE (service)); g_return_if_fail (in_headers != NULL); g_return_if_fail (COCKPIT_IS_WEB_RESPONSE (response)); g_return_if_fail (path != NULL); if (where == NULL) { host = "localhost"; } else if (where[0] == '@') { host = where + 1; } else if (where[0] == '$') { quoted_etag = g_strdup_printf ("\"%s\"", where); cache_type = COCKPIT_WEB_RESPONSE_CACHE_FOREVER; pragma = g_hash_table_lookup (in_headers, "Pragma"); if ((!pragma || !strstr (pragma, "no-cache")) && (g_strcmp0 (g_hash_table_lookup (in_headers, "If-None-Match"), where) == 0 || g_strcmp0 (g_hash_table_lookup (in_headers, "If-None-Match"), quoted_etag) == 0)) { cockpit_web_response_headers (response, 304, "Not Modified", 0, "ETag", quoted_etag, NULL); cockpit_web_response_complete (response); handled = TRUE; goto out; } transport = cockpit_web_service_find_transport (service, where + 1); if (!transport) goto out; host = cockpit_web_service_get_host (service, transport); if (!host) { g_warn_if_reached (); goto out; } } else { goto out; } cockpit_web_response_set_cache_type (response, cache_type); object = cockpit_transport_build_json ("command", "open", "payload", "http-stream1", "internal", "packages", "method", "GET", "host", host, "path", path, "binary", "raw", NULL); if (!transport) { transport = cockpit_web_service_ensure_transport (service, object); if (!transport) goto out; } if (where) { /* * Maybe send back a redirect to the checksum url. We only do this if actually * accessing a file, and not a some sort of data like '/checksum', or a root path * like '/' */ if (where[0] == '@' && strchr (path, '.')) { checksum = cockpit_web_service_get_checksum (service, transport); if (checksum) { handled = redirect_to_checksum_path (service, response, checksum, path); goto out; } } } out_headers = cockpit_web_server_new_table (); channel = cockpit_web_service_unique_channel (service); json_object_set_string_member (object, "channel", channel); if (quoted_etag) { /* * If we have a checksum, then use it as an ETag. It is intentional that * a cockpit-bridge version could (in the future) override this. */ g_hash_table_insert (out_headers, g_strdup ("ETag"), quoted_etag); quoted_etag = NULL; } heads = json_object_new (); g_hash_table_iter_init (&iter, in_headers); while (g_hash_table_iter_next (&iter, &key, &value)) { val = NULL; if (g_ascii_strcasecmp (key, "Host") == 0 || g_ascii_strcasecmp (key, "Cookie") == 0 || g_ascii_strcasecmp (key, "Referer") == 0 || g_ascii_strcasecmp (key, "Connection") == 0 || g_ascii_strcasecmp (key, "Pragma") == 0 || g_ascii_strcasecmp (key, "Cache-Control") == 0 || g_ascii_strcasecmp (key, "User-Agent") == 0 || g_ascii_strcasecmp (key, "Accept-Charset") == 0 || g_ascii_strcasecmp (key, "Accept-Ranges") == 0 || g_ascii_strcasecmp (key, "Content-Length") == 0 || g_ascii_strcasecmp (key, "Content-MD5") == 0 || g_ascii_strcasecmp (key, "Content-Range") == 0 || g_ascii_strcasecmp (key, "Range") == 0 || g_ascii_strcasecmp (key, "TE") == 0 || g_ascii_strcasecmp (key, "Trailer") == 0 || g_ascii_strcasecmp (key, "Upgrade") == 0 || g_ascii_strcasecmp (key, "Transfer-Encoding") == 0) continue; json_object_set_string_member (heads, key, value); g_free (val); } /* Parse the language out of the CockpitLang cookie */ language = cockpit_web_server_parse_cookie (in_headers, "CockpitLang"); if (language) json_object_set_string_member (heads, "Accept-Language", language); json_object_set_string_member (heads, "Host", host); json_object_set_object_member (object, "headers", heads); chesp = cockpit_channel_response_create (service, response, transport, cockpit_web_response_get_path (response), out_headers, object); if (!where) chesp->inject = cockpit_channel_inject_new (service, path); handled = TRUE; out: g_free (language); if (object) json_object_unref (object); g_free (quoted_etag); if (out_headers) g_hash_table_unref (out_headers); g_free (channel); if (!handled) cockpit_web_response_error (response, 404, NULL, NULL); }
static void send_login_html (CockpitWebResponse *response, CockpitHandlerData *ws, GHashTable *headers) { static const gchar *marker = "<meta insert_dynamic_content_here>"; CockpitWebFilter *filter; GBytes *environment; GError *error = NULL; GBytes *bytes; GBytes *url_bytes = NULL; CockpitWebFilter *filter2 = NULL; const gchar *url_root = NULL; gchar *base; gchar *language = NULL; gchar **languages = NULL; GBytes *po_bytes; CockpitWebFilter *filter3 = NULL; environment = build_environment (ws->os_release); filter = cockpit_web_inject_new (marker, environment, 1); g_bytes_unref (environment); cockpit_web_response_add_filter (response, filter); g_object_unref (filter); url_root = cockpit_web_response_get_url_root (response); if (url_root) base = g_strdup_printf ("<base href=\"%s/\">", url_root); else base = g_strdup ("<base href=\"/\">"); url_bytes = g_bytes_new_take (base, strlen(base)); filter2 = cockpit_web_inject_new (marker, url_bytes, 1); g_bytes_unref (url_bytes); cockpit_web_response_add_filter (response, filter2); g_object_unref (filter2); cockpit_web_response_set_cache_type (response, COCKPIT_WEB_RESPONSE_NO_CACHE); if (ws->login_po_html) { language = cockpit_web_server_parse_cookie (headers, "CockpitLang"); if (!language) { languages = cockpit_web_server_parse_languages (headers, NULL); language = languages[0]; } po_bytes = cockpit_web_response_negotiation (ws->login_po_html, NULL, language, NULL, &error); if (error) { g_message ("%s", error->message); g_clear_error (&error); } else { filter3 = cockpit_web_inject_new (marker, po_bytes, 1); g_bytes_unref (po_bytes); cockpit_web_response_add_filter (response, filter3); g_object_unref (filter3); } } bytes = cockpit_web_response_negotiation (ws->login_html, NULL, NULL, NULL, &error); if (error) { g_message ("%s", error->message); cockpit_web_response_error (response, 500, NULL, NULL); g_error_free (error); } else if (!bytes) { cockpit_web_response_error (response, 404, NULL, NULL); } else { /* The login Content-Security-Policy allows the page to have inline <script> and <style> tags. */ cockpit_web_response_headers (response, 200, "OK", -1, "Content-Type", "text/html", "Content-Security-Policy", "default-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss:", NULL); if (cockpit_web_response_queue (response, bytes)) cockpit_web_response_complete (response); g_bytes_unref (bytes); } g_strfreev (languages); }