Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
/**************************************************
 * 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;
}