static void dispatch_inbound_command (CockpitWebService *self, CockpitSocket *socket, GBytes *payload) { const gchar *problem = "protocol-error"; const gchar *command; const gchar *channel; JsonObject *options = NULL; gboolean valid = FALSE; valid = cockpit_transport_parse_command (payload, &command, &channel, &options); if (!valid) goto out; if (g_strcmp0 (command, "init") == 0) { problem = process_socket_init (self, socket, options); valid = (problem == NULL); goto out; } if (!socket->init_received) { g_message ("web socket did not send 'init' message first"); valid = FALSE; goto out; } valid = TRUE; if (g_strcmp0 (command, "open") == 0) { valid = process_and_relay_open (self, socket, channel, options); } else if (g_strcmp0 (command, "authorize") == 0) { valid = process_socket_authorize (self, socket, channel, options, payload); } else if (g_strcmp0 (command, "logout") == 0) { valid = process_logout (self, options); if (valid) { /* logout is broadcast to everyone */ if (!self->sent_done) cockpit_transport_send (self->transport, NULL, payload); } } else if (g_strcmp0 (command, "close") == 0) { if (channel == NULL) { g_warning ("got close command without a channel"); valid = FALSE; } else { valid = process_and_relay_close (self, socket, channel, payload); } } else if (g_strcmp0 (command, "kill") == 0) { valid = process_kill (self, socket, options, payload); } else if (!channel && g_strcmp0 (command, "ping") == 0) { valid = process_ping (self, socket, options); } else if (channel) { /* Relay anything with a channel by default */ if (!self->sent_done) cockpit_transport_send (self->transport, NULL, payload); } out: if (!valid) inbound_protocol_error (self, socket->connection, problem); if (options) json_object_unref (options); }
/************************************************** * Authentication phase * * - If AuthType != Persona, do nothing * - Handle POSTed assertions ("null" -> logout) * - If we have a cookie, set up user context **************************************************/ static int Auth_persona_check_cookie(request_rec *r) { char *szCookieValue=NULL; char *szRemoteIP=NULL; const char *assertion=NULL; if (!persona_authn_active(r)) { return DECLINED; } ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, ERRTAG "Auth_persona_check_cookie"); // We'll trade you a valid assertion for a session cookie! // this is a programmatic XHR request. persona_config_t *conf = ap_get_module_config(r->server->module_config, &authnz_persona_module); assertion = apr_table_get(r->headers_in, PERSONA_ASSERTION_HEADER); if (assertion) { if (strcmp(r->method, "POST")) { r->status = HTTP_METHOD_NOT_ALLOWED; ap_set_content_type(r, "application/json"); const char *error = "{\"status\": \"failure\", \"reason\":" "\"login must be performed with POST\"}"; ap_rwrite(error, strlen(error), r); return DONE; } if (!strcmp(assertion, "null")) { sendResetCookie(r); r->status = HTTP_OK; const char *status = "{\"status\": \"okay\"}"; ap_set_content_type(r, "application/json"); ap_rwrite(status, strlen(status), r); return DONE; } VerifyResult res = processAssertion(r, assertion); ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "Assertion received '%s'", assertion); if (res->verifiedEmail) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r, ERRTAG "email '%s' verified, vouched for by issuer '%s'", res->verifiedEmail, res->identityIssuer); Cookie cookie = apr_pcalloc(r->pool, sizeof(struct _Cookie)); cookie->verifiedEmail = res->verifiedEmail; cookie->identityIssuer = res->identityIssuer; cookie->created = apr_time_sec(r->request_time); sendSignedCookie(r, conf->secret, cookie); return DONE; } else { assert(res->errorResponse != NULL); r->status = HTTP_INTERNAL_SERVER_ERROR; ap_set_content_type(r, "application/json"); ap_rwrite(res->errorResponse, strlen(res->errorResponse), r); // upon assertion verification failure we return JSON explaining why return DONE; } } // handle logout via LogoutPath hit before letting valid cookies through if (conf->logout_path->len && !strncmp(r->uri, conf->logout_path->data, conf->logout_path->len)) { return process_logout(r); } // if there's a valid cookie, allow the user through szCookieValue = extractCookie(r, conf->secret, PERSONA_COOKIE_NAME); Cookie cookie = NULL; if (szCookieValue && (cookie = validateCookie(r, conf->secret, szCookieValue))) { r->user = (char *) cookie->verifiedEmail; apr_table_setn(r->notes, PERSONA_ISSUER_NOTE, cookie->identityIssuer); apr_table_setn(r->subprocess_env, "REMOTE_USER", cookie->verifiedEmail); ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r, ERRTAG "Valid auth cookie found, passthrough"); ap_custom_response(r, 401, (const char*) build_error_html); ap_custom_response(r, 403, (const char*) build_error_html); return OK; } ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r, ERRTAG "Persona cookie not found; not authorized! RemoteIP:%s",szRemoteIP); r->status = HTTP_UNAUTHORIZED; ap_set_content_type(r, "text/html"); ap_rwrite(src_signin_html, sizeof(src_signin_html), r); ap_rprintf(r, "var loggedInUser = undefined;\n"); ap_rwrite(PERSONA_END_PAGE, sizeof(PERSONA_END_PAGE), r); return DONE; }