static CockpitCreds * cookie_to_creds (CockpitAuth *self, const char *cookie) { CockpitCreds *creds = NULL; const char *prefix = "v=2;k="; const gsize n_prefix = 6; const gchar *id; if (!g_str_has_prefix (cookie, prefix)) { g_debug ("invalid or unsupported cookie: %s", cookie); return NULL; } id = cookie + n_prefix; creds = g_hash_table_lookup (self->authenticated, id); if (creds) { g_debug ("received credential id '%s' for user '%s'", id, cockpit_creds_get_user (creds)); cockpit_creds_ref (creds); } else g_debug ("received unknown/invalid credential id '%s'", id); return creds; }
static void stash_session_process (CockpitAuth *self, CockpitCreds *creds, CockpitPipe *proc) { /* Avoid calling destructors within the mutex */ if (g_hash_table_lookup (self->ready_sessions, creds)) { g_debug ("already had stashed session process for user"); } else { g_debug ("stashed session process for later"); g_hash_table_insert (self->ready_sessions, cockpit_creds_ref (creds), proc); } }
/** * cockpit_web_service_new: * @creds: credentials of user * @transport: an new cockpit transport that has not yet * sent an init message. * * Creates a new web service to serve web sockets and pass * messages to the given bridge. * * Returns: (transfer full): the new web service */ CockpitWebService * cockpit_web_service_new (CockpitCreds *creds, CockpitTransport *transport) { CockpitWebService *self; g_return_val_if_fail (creds != NULL, NULL); g_return_val_if_fail (transport != NULL, NULL); self = g_object_new (COCKPIT_TYPE_WEB_SERVICE, NULL); self->creds = cockpit_creds_ref (creds); self->transport = g_object_ref (transport); self->control_sig = g_signal_connect_after (self->transport, "control", G_CALLBACK (on_transport_control), self); self->recv_sig = g_signal_connect_after (self->transport, "recv", G_CALLBACK (on_transport_recv), self); self->closed_sig = g_signal_connect_after (self->transport, "closed", G_CALLBACK (on_transport_closed), self); return self; }
/** * cockpit_auth_start_session: * @creds: credentials for the session * * Start a local session process for the given credentials. * * If launching the session fails, then the pipe will be created in a * failed state, and will close shortly. A CockpitPipe is always returned. * * Returns: (transfer full): the new pipe */ CockpitPipe * cockpit_auth_start_session (CockpitCreds *creds) { CockpitPipe *pipe; CockpitPipe *auth_pipe = NULL; const gchar *password; GBytes *bytes = NULL; g_return_val_if_fail (creds != NULL, NULL); password = cockpit_creds_get_password (creds); if (password != NULL) { bytes = g_bytes_new_with_free_func (password, strlen (password), cockpit_creds_unref, cockpit_creds_ref (creds)); } pipe = spawn_session_process (cockpit_creds_get_user (creds), bytes, cockpit_creds_get_rhost (creds), &auth_pipe); if (auth_pipe) { /* * Any failure will come from the pipe exit code, but the session * needs our password (if we have one) so let it get sent. */ g_signal_connect (auth_pipe, "close", G_CALLBACK (g_object_unref), NULL); } if (!pipe) { pipe = g_object_new (COCKPIT_TYPE_PIPE, "name", "localhost", "problem", "internal-error", NULL); } return pipe; }
static char * creds_to_cookie (CockpitAuth *self, CockpitCreds *creds) { guint64 seed; gchar *cookie; char *id; seed = self->nonce_seed++; id = g_compute_hmac_for_data (G_CHECKSUM_SHA256, self->key->data, self->key->len, (guchar *)&seed, sizeof (seed)); cookie = g_strdup_printf ("v=2;k=%s", id); g_hash_table_insert (self->authenticated, id, cockpit_creds_ref (creds)); g_debug ("sending credential id '%s' for user '%s'", id, cockpit_creds_get_user (creds)); return cookie; }
static CockpitCreds * cockpit_auth_remote_login_finish (CockpitAuth *self, GAsyncResult *result, GHashTable *headers, CockpitTransport **transport, GError **error) { RemoteLoginData *rl; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), cockpit_auth_remote_login_async), NULL); if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return NULL; rl = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)); if (transport) *transport = g_object_ref (rl->transport); return cockpit_creds_ref (rl->creds); }