Exemple #1
0
static gboolean
on_handle_stream_socket (CockpitWebServer *server,
                         const gchar *path,
                         GIOStream *io_stream,
                         GHashTable *headers,
                         GByteArray *input,
                         guint in_length,
                         gpointer user_data)
{
  CockpitTransport *transport;
  const gchar *query = NULL;
  CockpitCreds *creds;
  CockpitPipe *pipe;
  gchar *value;
  gchar **env;

  if (!g_str_has_prefix (path, "/cockpit/socket"))
    return FALSE;

  if (path[15] == '?')
    query = path + 16;
  else if (path[15] != '\0')
    return FALSE;

  if (service)
    {
      g_object_ref (service);
    }
  else
    {
      value = g_strdup_printf ("%d", server_port);
      env = g_environ_setenv (g_get_environ (), "COCKPIT_TEST_SERVER_PORT", value, TRUE);

      creds = cockpit_creds_new (g_get_user_name (), "test",
                                 COCKPIT_CRED_CSRF_TOKEN, "myspecialtoken",
                                 NULL);
      pipe = cockpit_pipe_spawn ((const gchar **)bridge_argv, (const gchar **)env, NULL, FALSE);
      transport = cockpit_pipe_transport_new (pipe);
      service = cockpit_web_service_new (creds, transport);
      cockpit_creds_unref (creds);
      g_object_unref (transport);
      g_object_unref (pipe);

      g_free (value);
      g_strfreev (env);

      /* Clear the pointer automatically when service is done */
      g_object_add_weak_pointer (G_OBJECT (service), (gpointer *)&service);
    }

  if (query)
    cockpit_channel_socket_open (service, "/cockpit/socket", query, io_stream, headers, input);
  else
    cockpit_web_service_socket (service, "/cockpit/socket", io_stream, headers, input);

  /* Keeps ref on itself until it closes */
  g_object_unref (service);

  return TRUE;
}
Exemple #2
0
/* Called by @server when handling HTTP requests to /socket - runs in a separate
 * thread dedicated to the request so it may do blocking I/O
 */
static gboolean
on_handle_stream_socket (CockpitWebServer *server,
                         CockpitWebServerRequestType reqtype,
                         const gchar *resource,
                         GIOStream *io_stream,
                         GHashTable *headers,
                         GByteArray *input,
                         guint in_length,
                         gpointer user_data)
{
  CockpitWebService *service;
  CockpitCreds *creds;

  if (!g_str_equal (resource, "/socket"))
    return FALSE;

  creds = cockpit_creds_new (g_get_user_name (), NULL);

  service = cockpit_web_service_new (creds, NULL);

  cockpit_web_service_socket (service, io_stream, headers, input);

  /* Keeps ref on itself until it closes */
  g_object_unref (service);

  cockpit_creds_unref (creds);
  return TRUE;
}
Exemple #3
0
static void
cockpit_auth_remote_login_async (CockpitAuth *self,
                                 GHashTable *headers,
                                 const gchar *remote_peer,
                                 GAsyncReadyCallback callback,
                                 gpointer user_data)
{
  GSimpleAsyncResult *task;
  CockpitCreds *creds = NULL;
  RemoteLoginData *rl;
  const gchar *password;
  GBytes *input;
  gchar *type = NULL;
  gchar *user = NULL;

  task = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
                                    cockpit_auth_remote_login_async);

  input = cockpit_auth_parse_authorization (headers, &type);

  if (type && input && g_str_equal (type, "basic"))
    {
      password = parse_basic_auth_password (input, &user);
      if (password && user)
        {
          creds = cockpit_creds_new (user,
                                     COCKPIT_CRED_PASSWORD, password,
                                     COCKPIT_CRED_RHOST, remote_peer,
                                     NULL);
        }
      g_free (user);
    }

  if (creds)
    {
      rl = g_new0 (RemoteLoginData, 1);
      rl->creds = creds;
      rl->transport = g_object_new (COCKPIT_TYPE_SSH_TRANSPORT,
                                    "host", "127.0.0.1",
                                    "port", cockpit_ws_specific_ssh_port,
                                    "command", cockpit_ws_bridge_program,
                                    "creds", creds,
                                    "ignore-key", TRUE,
                                    NULL);

      g_simple_async_result_set_op_res_gpointer (task, rl, remote_login_data_free);
      g_signal_connect (rl->transport, "result", G_CALLBACK (on_remote_login_done), g_object_ref (task));
    }
  else
    {
      g_simple_async_result_set_error (task, COCKPIT_ERROR, COCKPIT_ERROR_AUTHENTICATION_FAILED,
                                       "Basic authentication required");
      g_simple_async_result_complete_in_idle (task);
    }

  g_free (type);
  g_object_unref (task);
}
Exemple #4
0
static CockpitCreds *
create_creds_for_spawn_authenticated (CockpitAuth *self,
                                      const gchar *user,
                                      AuthData *ad,
                                      JsonObject *results,
                                      const gchar *raw_data)
{
  const gchar *password = NULL;
  const gchar *gssapi_creds = NULL;
  CockpitCreds *creds = NULL;
  gchar *csrf_token;

  /*
   * Dig the password out of the authorization header, rather than having
   * passing it back and forth possibly leaking it.
   */

  if (g_str_equal (ad->auth_type, "basic") ||
      g_str_equal (ad->auth_type, SSH_SECTION))
    {
      password = parse_basic_auth_password (ad->authorization, NULL);
    }

  if (!cockpit_json_get_string (results, "gssapi-creds", NULL, &gssapi_creds))
    {
      g_warning ("received bad gssapi-creds");
      gssapi_creds = NULL;
    }

  csrf_token = cockpit_auth_nonce (self);

  creds = cockpit_creds_new (user,
                             ad->application,
                             COCKPIT_CRED_LOGIN_DATA, raw_data,
                             COCKPIT_CRED_PASSWORD, password,
                             COCKPIT_CRED_RHOST, ad->remote_peer,
                             COCKPIT_CRED_GSSAPI, gssapi_creds,
                             COCKPIT_CRED_CSRF_TOKEN, csrf_token,
                             NULL);

  g_free (csrf_token);
  return creds;
}
Exemple #5
0
static CockpitCreds *
create_creds_for_authenticated (const char *user,
                                SessionLoginData *sl,
                                JsonObject *results)
{
  const gchar *fullname = NULL;
  const gchar *password = NULL;
  const gchar *gssapi_creds = NULL;

  /*
   * Dig the password out of the authorization header, rather than having
   * cockpit-session pass it back and forth possibly leaking it.
   */

  if (g_str_equal (sl->auth_type, "basic"))
    password = parse_basic_auth_password (sl->authorization, NULL);

  if (!cockpit_json_get_string (results, "gssapi-creds", NULL, &gssapi_creds))
    {
      g_warning ("received bad gssapi-creds from cockpit-session");
      gssapi_creds = NULL;
    }

  if (!cockpit_json_get_string (results, "full-name", NULL, &fullname))
    {
      g_warning ("received bad full-name from cockpit-session");
      fullname = NULL;
    }

  /* TODO: Try to avoid copying password */
  return cockpit_creds_new (user,
                            sl->application,
                            COCKPIT_CRED_FULLNAME, fullname,
                            COCKPIT_CRED_PASSWORD, password,
                            COCKPIT_CRED_RHOST, sl->remote_peer,
                            COCKPIT_CRED_GSSAPI, gssapi_creds,
                            NULL);
}
Exemple #6
0
static CockpitCreds *
parse_auth_results (LoginData *login,
                    GError **error)
{
  CockpitCreds *creds = NULL;
  GByteArray *buffer;
  GError *json_error = NULL;
  const gchar *pam_user;
  JsonObject *results;
  gconstpointer data;
  gint64 code = -1;
  gchar *password;
  gsize length;

  buffer = cockpit_pipe_get_buffer (login->auth_pipe);
  results = cockpit_json_parse_object ((const gchar *)buffer->data, buffer->len, &json_error);

  if (g_error_matches (json_error, JSON_PARSER_ERROR, JSON_PARSER_ERROR_INVALID_DATA))
    {
      g_message ("got non-utf8 user name from cockpit-session");
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
                   "Login user name is not UTF8 encoded");
      g_error_free (json_error);
      return NULL;
    }

  if (!results)
    {
      g_warning ("couldn't parse session auth output: %s", json_error->message);
      g_error_free (json_error);
      return NULL;
    }

  if (!cockpit_json_get_int (results, "pam-result", -1, &code) || code < 0)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
                   "Invalid data from session process: bad PAM result");
    }
  else if (code == PAM_SUCCESS)
    {
      if (!cockpit_json_get_string (results, "user", NULL, &pam_user) || !pam_user)
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
                       "Invalid data from session process: missing user");
        }
      else
        {
          g_debug ("user authenticated as %s", pam_user);

          /* TODO: Try to avoid copying password */
          data = g_bytes_get_data (login->password, &length);
          password = g_strndup (data, length);
          creds = cockpit_creds_new (pam_user,
                                     COCKPIT_CRED_PASSWORD, password,
                                     COCKPIT_CRED_RHOST, login->remote_peer,
                                     NULL);
          g_free (password);
        }
    }
  else if (code == PAM_AUTH_ERR || code == PAM_USER_UNKNOWN)
    {
      g_debug ("authentication failed: %d", (int)code);
      g_set_error (error, COCKPIT_ERROR, COCKPIT_ERROR_AUTHENTICATION_FAILED,
                   "Authentication failed");
    }
  else
    {
      g_debug ("pam error: %d", (int)code);
      g_set_error (error, COCKPIT_ERROR, COCKPIT_ERROR_FAILED,
                   "%s", pam_strerror (NULL, code));
    }

  json_object_unref (results);
  return creds;
}
Exemple #7
0
static gboolean
on_handle_stream_socket (CockpitWebServer *server,
                         const gchar *path,
                         GIOStream *io_stream,
                         GHashTable *headers,
                         GByteArray *input,
                         gpointer user_data)
{
  CockpitTransport *transport;
  const gchar *query = NULL;
  CockpitCreds *creds;
  int session_stdin = -1;
  int session_stdout = -1;
  GError *error = NULL;
  GPid pid = 0;

  gchar *value;
  gchar **env;
  gchar **argv;

  if (!g_str_has_prefix (path, "/cockpit/socket"))
    return FALSE;

  if (path[15] == '?')
    {
      query = path + 16;
    }
  else if (path[15] != '\0')
    {
      return FALSE;
    }

  if (service)
    {
      g_object_ref (service);
    }
  else
    {
      g_clear_object (&bridge);

      value = g_strdup_printf ("%d", server_port);
      env = g_environ_setenv (g_get_environ (), "COCKPIT_TEST_SERVER_PORT", value, TRUE);

      argv = g_strdupv (bridge_argv);
      if (query)
        argv[g_strv_length (argv) - 1] = g_strdup (query);

      g_spawn_async_with_pipes (NULL, argv, env,
                                G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
                                NULL, NULL, &pid, &session_stdin, &session_stdout, NULL, &error);

      g_strfreev (env);
      g_free (argv);
      g_free (value);

      if (error)
        {
          g_critical ("couldn't run bridge %s: %s", bridge_argv[0], error->message);
          return FALSE;
        }

      bridge = g_object_new (COCKPIT_TYPE_PIPE,
                             "name", "test-server-bridge",
                             "in-fd", session_stdout,
                             "out-fd", session_stdin,
                             "pid", pid,
                             NULL);

      creds = cockpit_creds_new (g_get_user_name (), "test",
                                 COCKPIT_CRED_CSRF_TOKEN, "myspecialtoken",
                                 NULL);

      transport = cockpit_pipe_transport_new (bridge);
      service = cockpit_web_service_new (creds, transport);
      cockpit_creds_unref (creds);
      g_object_unref (transport);

      /* Clear the pointer automatically when service is done */
      g_object_add_weak_pointer (G_OBJECT (service), (gpointer *)&service);
    }

  cockpit_web_service_socket (service, path, io_stream, headers, input);

  /* Keeps ref on itself until it closes */
  g_object_unref (service);

  return TRUE;
}