-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
login: Prevent multiple logins in a single browser session #20860
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -338,6 +338,27 @@ import "./login.scss"; | |
event.stopPropagation(); | ||
} | ||
|
||
function deal_with_multihost() { | ||
// If we are currently logged in to some machine, but still | ||
// end up on the login page, we are about to load resources | ||
// from two machines into the same browser origin. This needs | ||
// to be allowed explicitly via a configuration setting. | ||
|
||
const logged_into = environment.logged_into || []; | ||
const cur_machine = logged_into.length > 0 ? logged_into[0] : null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
(but if you prefer this, it's fine) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks too much like Perl for my taste... :-) but let's do it. |
||
|
||
function redirect_to_current_machine() { | ||
if (cur_machine === ".") { | ||
login_reload("/"); | ||
} else { | ||
login_reload("/=" + cur_machine); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This added line is not executed by any test. |
||
} | ||
} | ||
|
||
if (cur_machine && !environment.page.allow_multihost) | ||
redirect_to_current_machine(); | ||
} | ||
|
||
function boot() { | ||
window.onload = null; | ||
|
||
|
@@ -348,6 +369,8 @@ import "./login.scss"; | |
document.documentElement.dir = window.cockpit_po[""]["language-direction"]; | ||
} | ||
|
||
deal_with_multihost(); | ||
|
||
setup_path_globals(window.location.pathname); | ||
|
||
/* Determine if we are nested or not, and switch styles */ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1241,13 +1241,38 @@ base64_decode_string (const char *enc) | |
return dec; | ||
} | ||
|
||
static CockpitSession * | ||
session_for_cookie_value (CockpitAuth *self, | ||
const gchar *cookie_value) | ||
{ | ||
gchar *decoded = NULL; | ||
const char *prefix = "v=2;k="; | ||
CockpitSession *ret = NULL; | ||
|
||
g_return_val_if_fail (self != NULL, FALSE); | ||
|
||
if (cookie_value) | ||
{ | ||
decoded = base64_decode_string (cookie_value); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can use update: Oh, this is moved code. OK to keep if you prefer not to touch it. |
||
if (decoded != NULL) | ||
{ | ||
if (g_str_has_prefix (decoded, prefix)) | ||
ret = g_hash_table_lookup (self->sessions, decoded); | ||
else | ||
g_debug ("invalid or unsupported cookie: %s", decoded); | ||
|
||
g_free (decoded); | ||
} | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
static CockpitSession * | ||
session_for_request (CockpitAuth *self, | ||
CockpitWebRequest *request) | ||
{ | ||
gchar *cookie = NULL; | ||
gchar *raw = NULL; | ||
const char *prefix = "v=2;k="; | ||
CockpitSession *ret = NULL; | ||
gchar *application; | ||
gchar *cookie_name = NULL; | ||
|
@@ -1260,23 +1285,12 @@ session_for_request (CockpitAuth *self, | |
|
||
cookie_name = application_cookie_name (application); | ||
raw = cockpit_web_request_parse_cookie (request, cookie_name); | ||
if (raw) | ||
{ | ||
cookie = base64_decode_string (raw); | ||
if (cookie != NULL) | ||
{ | ||
if (g_str_has_prefix (cookie, prefix)) | ||
ret = g_hash_table_lookup (self->sessions, cookie); | ||
else | ||
g_debug ("invalid or unsupported cookie: %s", cookie); | ||
ret = session_for_cookie_value (self, raw); | ||
|
||
/* We must never find the default session based on a cookie */ | ||
g_assert (!ret || !g_str_equal (ret->cookie, LOCAL_SESSION)); | ||
g_assert (!ret || !g_str_equal (ret->name, LOCAL_SESSION)); | ||
g_free (cookie); | ||
} | ||
g_free (raw); | ||
} | ||
/* We must never find the default session based on a cookie */ | ||
g_assert (!ret || !g_str_equal (ret->cookie, LOCAL_SESSION)); | ||
g_assert (!ret || !g_str_equal (ret->name, LOCAL_SESSION)); | ||
g_free (raw); | ||
|
||
/* Check for a default session for auto-login */ | ||
if (!ret) | ||
|
@@ -1309,6 +1323,13 @@ cockpit_auth_check_cookie (CockpitAuth *self, | |
} | ||
} | ||
|
||
gboolean | ||
cockpit_auth_is_valid_cookie_value (CockpitAuth *self, | ||
const gchar *cookie_value) | ||
{ | ||
return session_for_cookie_value (self, cookie_value) != NULL; | ||
} | ||
|
||
void | ||
cockpit_auth_local_async (CockpitAuth *self, | ||
const gchar *user, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -102,7 +102,10 @@ gboolean cockpit_auth_local_finish (CockpitAuth *self, | |
CockpitWebService * cockpit_auth_check_cookie (CockpitAuth *self, | ||
CockpitWebRequest *request); | ||
|
||
gchar * cockpit_auth_parse_application (const gchar *path, | ||
gboolean cockpit_auth_is_valid_cookie_value (CockpitAuth *self, | ||
const gchar *cookie_value); | ||
|
||
gchar * cockpit_auth_parse_application (const gchar *path, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please outdent again |
||
gboolean *is_host); | ||
|
||
gchar * cockpit_auth_empty_cookie_value (const gchar *path, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -277,8 +277,47 @@ add_page_to_environment (JsonObject *object, | |
json_object_set_object_member (object, "page", page); | ||
} | ||
|
||
static void | ||
add_logged_into_to_environment (JsonObject *object, | ||
CockpitAuth *auth, | ||
GHashTable *request_headers) | ||
{ | ||
JsonArray *logged_into = json_array_new (); | ||
|
||
gchar *h = g_hash_table_lookup (request_headers, "Cookie"); | ||
while (h && *h) { | ||
const gchar *start = h; | ||
while (*h && *h != '=') | ||
h++; | ||
const gchar *equal = h; | ||
while (*h && *h != ';') | ||
h++; | ||
const gchar *end = h; | ||
if (*h) | ||
h++; | ||
while (*h && *h == ' ') | ||
h++; | ||
|
||
if (*equal != '=') | ||
continue; | ||
|
||
g_autofree gchar *value = g_strndup (equal + 1, end - equal - 1); | ||
|
||
if (!cockpit_auth_is_valid_cookie_value (auth, value)) | ||
continue; | ||
|
||
g_autofree gchar *name = g_strndup (start, equal - start); | ||
Comment on lines
+287
to
+309
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, do you want There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, that would be the second time in my life that I use sscanf... hmm. |
||
if (g_str_equal (name, "cockpit")) | ||
json_array_add_string_element(logged_into, "."); | ||
else if (g_str_has_prefix (name, "machine-cockpit+")) | ||
json_array_add_string_element(logged_into, name + strlen("machine-cockpit+")); | ||
} | ||
|
||
json_object_set_array_member (object, "logged_into", logged_into); | ||
} | ||
|
||
static GBytes * | ||
build_environment (GHashTable *os_release) | ||
build_environment (GHashTable *os_release, CockpitAuth *auth, GHashTable *request_headers) | ||
{ | ||
/* | ||
* We don't include entirety of os-release into the | ||
|
@@ -310,6 +349,7 @@ build_environment (GHashTable *os_release) | |
json_object_set_boolean_member (object, "is_cockpit_client", is_cockpit_client); | ||
|
||
add_page_to_environment (object, is_cockpit_client); | ||
add_logged_into_to_environment (object, auth, request_headers); | ||
|
||
hostname = g_malloc0 (HOST_NAME_MAX + 1); | ||
gethostname (hostname, HOST_NAME_MAX); | ||
|
@@ -386,7 +426,7 @@ send_login_html (CockpitWebResponse *response, | |
GBytes *po_bytes; | ||
CockpitWebFilter *filter3 = NULL; | ||
|
||
environment = build_environment (ws->os_release); | ||
environment = build_environment (ws->os_release, ws->auth, headers); | ||
filter = cockpit_web_inject_new (marker, environment, 1); | ||
g_bytes_unref (environment); | ||
cockpit_web_response_add_filter (response, filter); | ||
|
@@ -455,6 +495,7 @@ send_login_html (CockpitWebResponse *response, | |
"Content-Security-Policy", content_security_policy, | ||
"Set-Cookie", cookie_line, | ||
NULL); | ||
cockpit_web_response_set_cache_type (response, COCKPIT_WEB_RESPONSE_NO_CACHE); | ||
if (cockpit_web_response_queue (response, bytes)) | ||
cockpit_web_response_complete (response); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test.