|
Packit |
8ea169 |
/*
|
|
Packit |
8ea169 |
Copyright (C) 2015 ABRT team
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
This program is free software; you can redistribute it and/or modify
|
|
Packit |
8ea169 |
it under the terms of the GNU General Public License as published by
|
|
Packit |
8ea169 |
the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
8ea169 |
(at your option) any later version.
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
This program is distributed in the hope that it will be useful,
|
|
Packit |
8ea169 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
8ea169 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
8ea169 |
GNU General Public License for more details.
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
You should have received a copy of the GNU General Public License along
|
|
Packit |
8ea169 |
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit |
8ea169 |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
8ea169 |
#include <config.h>
|
|
Packit |
8ea169 |
#endif
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
#include "abrt_problems2_session.h"
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
#include "libabrt.h"
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static PolkitAuthority *s_pk_authority;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
PolkitAuthority *abrt_p2_session_class_set_polkit_authority(PolkitAuthority *pk_authority)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
if (s_pk_authority != NULL)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_warning("Session: polkit Authority already initialized");
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/*
|
|
Packit |
8ea169 |
* Introduce something like this to libreport
|
|
Packit |
8ea169 |
if (g_verbose > 3)
|
|
Packit |
8ea169 |
abort();
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
return s_pk_authority;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
s_pk_authority = pk_authority;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return s_pk_authority;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
PolkitAuthority *abrt_p2_session_class_polkit_authority(void)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
if (s_pk_authority == NULL)
|
|
Packit |
8ea169 |
log_debug("Session: Polkit Authority not-yet initialized");
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return s_pk_authority;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
PolkitAuthority *abrt_p2_session_class_release_polkit_authority(void)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
PolkitAuthority *pk_authority = s_pk_authority;
|
|
Packit |
8ea169 |
s_pk_authority = NULL;
|
|
Packit |
8ea169 |
return pk_authority;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
typedef struct
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
char *p2s_caller;
|
|
Packit |
8ea169 |
uid_t p2s_uid;
|
|
Packit |
8ea169 |
int p2s_state;
|
|
Packit |
8ea169 |
GList *p2s_tasks;
|
|
Packit |
8ea169 |
uint32_t p2s_task_indexer;
|
|
Packit |
8ea169 |
GHashTable *p2s_tokens;
|
|
Packit |
8ea169 |
struct check_auth_cb_params *p2s_auth_rq;
|
|
Packit |
8ea169 |
PolkitSubject *p2s_pk_subject;
|
|
Packit |
8ea169 |
} AbrtP2SessionPrivate;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
enum
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
ABRT_P2_SESSION_STATE_INIT,
|
|
Packit |
8ea169 |
ABRT_P2_SESSION_STATE_PENDING,
|
|
Packit |
8ea169 |
ABRT_P2_SESSION_STATE_AUTH,
|
|
Packit |
8ea169 |
};
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
struct _AbrtP2Session
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
GObject parent_instance;
|
|
Packit |
8ea169 |
AbrtP2SessionPrivate *pv;
|
|
Packit |
8ea169 |
};
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
G_DEFINE_TYPE_WITH_PRIVATE(AbrtP2Session, abrt_p2_session, G_TYPE_OBJECT)
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
struct check_auth_cb_params
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
AbrtP2Session *session;
|
|
Packit |
8ea169 |
GCancellable *cancellable;
|
|
Packit |
8ea169 |
PolkitDetails *details;
|
|
Packit |
8ea169 |
};
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
enum {
|
|
Packit |
8ea169 |
SN_AUTHORIZATION_CHANGED,
|
|
Packit |
8ea169 |
SN_LAST_SIGNAL
|
|
Packit |
8ea169 |
} SignalNumber;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static guint s_signals[SN_LAST_SIGNAL] = { 0 };
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static void abrt_p2_session_finalize(GObject *gobject)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
AbrtP2SessionPrivate *pv = abrt_p2_session_get_instance_private(ABRT_P2_SESSION(gobject));
|
|
Packit |
8ea169 |
free(pv->p2s_caller);
|
|
Packit |
8ea169 |
g_hash_table_destroy(pv->p2s_tokens);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* If there is ongoing authorization, */
|
|
Packit |
8ea169 |
/* tell the callback that it must not touch session.*/
|
|
Packit |
8ea169 |
if (pv->p2s_auth_rq != NULL)
|
|
Packit |
8ea169 |
pv->p2s_auth_rq->session = NULL;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (pv->p2s_pk_subject != NULL)
|
|
Packit |
8ea169 |
g_object_unref(pv->p2s_pk_subject);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static void abrt_p2_session_class_init(AbrtP2SessionClass *klass)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
Packit |
8ea169 |
object_class->finalize = abrt_p2_session_finalize;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
s_signals[SN_AUTHORIZATION_CHANGED] = g_signal_new ("authorization-changed",
|
|
Packit |
8ea169 |
G_TYPE_FROM_CLASS (klass),
|
|
Packit |
8ea169 |
G_SIGNAL_RUN_LAST,
|
|
Packit |
8ea169 |
G_STRUCT_OFFSET(AbrtP2SessionClass, authorization_changed),
|
|
Packit |
8ea169 |
/*accumulator*/NULL, /*accu_data*/NULL,
|
|
Packit |
8ea169 |
g_cclosure_marshal_VOID__INT,
|
|
Packit |
8ea169 |
G_TYPE_NONE,
|
|
Packit |
8ea169 |
/*n_params*/1,
|
|
Packit |
8ea169 |
G_TYPE_INT);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static void abrt_p2_session_init(AbrtP2Session *self)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
self->pv = abrt_p2_session_get_instance_private(self);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static void emit_authorization_changed(AbrtP2Session *session,
|
|
Packit |
8ea169 |
AbrtP2SessionAuthChangedStatus status)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
g_signal_emit(session,
|
|
Packit |
8ea169 |
s_signals[SN_AUTHORIZATION_CHANGED],
|
|
Packit |
8ea169 |
0,
|
|
Packit |
8ea169 |
(gint32)status);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static void change_state(AbrtP2Session *session, int new_state)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
if (session->pv->p2s_state == new_state)
|
|
Packit |
8ea169 |
return;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
AbrtP2SessionAuthChangedStatus value = -1;
|
|
Packit |
8ea169 |
int old_state = session->pv->p2s_state;
|
|
Packit |
8ea169 |
session->pv->p2s_state = new_state;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (old_state == ABRT_P2_SESSION_STATE_INIT && new_state == ABRT_P2_SESSION_STATE_PENDING)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_debug("Authorization request is pending");
|
|
Packit |
8ea169 |
value = ABRT_P2_SESSION_CHANGED_PENDING;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
else if (old_state == ABRT_P2_SESSION_STATE_INIT && new_state == ABRT_P2_SESSION_STATE_AUTH)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_debug("Authorization has been granted");
|
|
Packit |
8ea169 |
value = ABRT_P2_SESSION_CHANGED_AUTHORIZED;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
else if (old_state == ABRT_P2_SESSION_STATE_PENDING && new_state == ABRT_P2_SESSION_STATE_AUTH)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_debug("Authorization has been acquired");
|
|
Packit |
8ea169 |
value = ABRT_P2_SESSION_CHANGED_AUTHORIZED;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
else if (old_state == ABRT_P2_SESSION_STATE_AUTH && new_state == ABRT_P2_SESSION_STATE_INIT)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_debug("Authorization request has been lost");
|
|
Packit |
8ea169 |
value = ABRT_P2_SESSION_CHANGED_NOT_AUTHORIZED;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
else if (old_state == ABRT_P2_SESSION_STATE_PENDING && new_state == ABRT_P2_SESSION_STATE_INIT)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_debug("Authorization request has failed");
|
|
Packit |
8ea169 |
value = ABRT_P2_SESSION_CHANGED_FAILED;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
else
|
|
Packit |
8ea169 |
goto forgotten_state;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
emit_authorization_changed(session, value);
|
|
Packit |
8ea169 |
return;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
forgotten_state:
|
|
Packit |
8ea169 |
error_msg("BUG: unsupported state, current : %d, new : %d",
|
|
Packit |
8ea169 |
session->pv->p2s_state,
|
|
Packit |
8ea169 |
new_state);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
#ifdef HAVE_POLKIT
|
|
Packit |
8ea169 |
static void check_authorization_callback(GObject *source,
|
|
Packit |
8ea169 |
GAsyncResult *res,
|
|
Packit |
8ea169 |
gpointer user_data)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
GError *error = NULL;
|
|
Packit |
8ea169 |
PolkitAuthorizationResult *result = NULL;
|
|
Packit |
8ea169 |
result = polkit_authority_check_authorization_finish(POLKIT_AUTHORITY(source),
|
|
Packit |
8ea169 |
res,
|
|
Packit |
8ea169 |
&error);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
int new_state = ABRT_P2_SESSION_STATE_INIT;
|
|
Packit |
8ea169 |
if (result == NULL)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
error_msg("Polkit authorization failed: %s", error->message);
|
|
Packit |
8ea169 |
g_error_free(error);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
else
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
if (polkit_authorization_result_get_is_authorized(result))
|
|
Packit |
8ea169 |
new_state = ABRT_P2_SESSION_STATE_AUTH;
|
|
Packit |
8ea169 |
else
|
|
Packit |
8ea169 |
/* We do not support polkit_authorization_result_get_is_challenge */
|
|
Packit |
8ea169 |
log_debug("Not authorized");
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
g_object_unref(result);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
struct check_auth_cb_params *params = (struct check_auth_cb_params *)user_data;
|
|
Packit |
8ea169 |
AbrtP2Session *session = params->session;
|
|
Packit |
8ea169 |
g_object_unref(params->cancellable);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (params->details != NULL)
|
|
Packit |
8ea169 |
g_object_unref(params->details);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
free(params);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* It might happen that the session had been destroyed before the callback
|
|
Packit |
8ea169 |
* was called (e.g. if you programmatically cancel the operation, this
|
|
Packit |
8ea169 |
* callback is called in the next main loop iteration). */
|
|
Packit |
8ea169 |
if (session != NULL)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
change_state(session, new_state);
|
|
Packit |
8ea169 |
session->pv->p2s_auth_rq = NULL;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
else
|
|
Packit |
8ea169 |
log_debug("Operation finished after the session had been destroyed");
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
#endif
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static void authorization_request_initialize(AbrtP2Session *session, GVariant *parameters)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
#ifdef HAVE_POLKIT
|
|
Packit |
8ea169 |
struct check_auth_cb_params *auth_rq = xmalloc(sizeof(*auth_rq));
|
|
Packit |
8ea169 |
auth_rq->session = session;
|
|
Packit |
8ea169 |
auth_rq->cancellable = g_cancellable_new();
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
auth_rq->details = NULL;
|
|
Packit |
8ea169 |
if (parameters != NULL)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
GVariant *message = g_variant_lookup_value(parameters,
|
|
Packit |
8ea169 |
"message",
|
|
Packit |
8ea169 |
G_VARIANT_TYPE_STRING);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (message != NULL)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
auth_rq->details = polkit_details_new();
|
|
Packit |
8ea169 |
polkit_details_insert(auth_rq->details,
|
|
Packit |
8ea169 |
"polkit.message",
|
|
Packit |
8ea169 |
g_variant_get_string(message,
|
|
Packit |
8ea169 |
NULL));
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
g_variant_unref(message);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
session->pv->p2s_auth_rq = auth_rq;
|
|
Packit |
8ea169 |
change_state(session, ABRT_P2_SESSION_STATE_PENDING);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* http://www.freedesktop.org/software/polkit/docs/latest/polkit-apps.html
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
if (session->pv->p2s_pk_subject == NULL)
|
|
Packit |
8ea169 |
session->pv->p2s_pk_subject = polkit_system_bus_name_new(session->pv->p2s_caller);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* If you cancel this operation programmatically, you might get the
|
|
Packit |
8ea169 |
* following warning message:
|
|
Packit |
8ea169 |
WARNING **: Error cancelling authorization check:
|
|
Packit |
8ea169 |
GDBus.Error:org.freedesktop.PolicyKit1.Error.Failed:
|
|
Packit |
8ea169 |
No such cancellation_id `cancellation-id-1' for name :1.257
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
The message is returned by polkitbackend and it just means that there
|
|
Packit |
8ea169 |
were nothing to cancel. Probably because the operation was already
|
|
Packit |
8ea169 |
finished or not-yet started.
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
polkit_authority_check_authorization(abrt_p2_session_class_polkit_authority(),
|
|
Packit |
8ea169 |
session->pv->p2s_pk_subject,
|
|
Packit |
8ea169 |
"org.freedesktop.problems.getall",
|
|
Packit |
8ea169 |
auth_rq->details,
|
|
Packit |
8ea169 |
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
|
|
Packit |
8ea169 |
auth_rq->cancellable,
|
|
Packit |
8ea169 |
check_authorization_callback,
|
|
Packit |
8ea169 |
auth_rq);
|
|
Packit |
8ea169 |
#else
|
|
Packit |
8ea169 |
change_state(session, ABRT_P2_SESSION_STATE_AUTH);
|
|
Packit |
8ea169 |
#endif
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
AbrtP2Session *abrt_p2_session_new(char *caller, uid_t uid)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
AbrtP2Session *session = g_object_new(TYPE_ABRT_P2_SESSION, NULL);
|
|
Packit |
8ea169 |
session->pv->p2s_caller = caller;
|
|
Packit |
8ea169 |
session->pv->p2s_uid = uid;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (session->pv->p2s_uid == 0)
|
|
Packit |
8ea169 |
session->pv->p2s_state = ABRT_P2_SESSION_STATE_AUTH;
|
|
Packit |
8ea169 |
else
|
|
Packit |
8ea169 |
session->pv->p2s_state = ABRT_P2_SESSION_STATE_INIT;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
session->pv->p2s_tokens = g_hash_table_new_full(g_str_hash,
|
|
Packit |
8ea169 |
g_str_equal,
|
|
Packit |
8ea169 |
g_free,
|
|
Packit |
8ea169 |
NULL);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return session;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
const char *abrt_p2_session_generate_token(AbrtP2Session *session,
|
|
Packit |
8ea169 |
unsigned int duration,
|
|
Packit |
8ea169 |
GError **error)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
if (session->pv->p2s_state != ABRT_P2_SESSION_STATE_AUTH)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
Packit |
8ea169 |
"Session is not authorized");
|
|
Packit |
8ea169 |
return NULL;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
#define SESSION_TOKEN_LENGTH 16
|
|
Packit |
8ea169 |
static const char *const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (duration == 0)
|
|
Packit |
8ea169 |
duration = 5;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
FILE *urandom = fopen("/dev/urandom", "rb");
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (urandom == NULL)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
perror_msg("fopen(/dev/urandom, rb)");
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
Packit |
8ea169 |
"Failed to open /dev/urandom for reading");
|
|
Packit |
8ea169 |
return NULL;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
unsigned int seed = 0;
|
|
Packit |
8ea169 |
const size_t r = fread(&seed, 1, sizeof(seed), urandom);
|
|
Packit |
8ea169 |
fclose(urandom);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (sizeof(seed) != r)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
perror_msg("fread(unsigned int, /dev/urandom)");
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
Packit |
8ea169 |
"Failed to read 'unsigned int' from /dev/urandom");
|
|
Packit |
8ea169 |
return NULL;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
char *token = xmalloc((SESSION_TOKEN_LENGTH + 1) * sizeof(char));
|
|
Packit |
8ea169 |
for (char *iter = token; iter < token + SESSION_TOKEN_LENGTH; ++iter)
|
|
Packit |
8ea169 |
*iter = alphabet[(int)(strlen(alphabet) * (rand_r(&seed) / (double)RAND_MAX))];
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
token[SESSION_TOKEN_LENGTH] = '\0';
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
const time_t curtime = time(NULL);
|
|
Packit |
8ea169 |
if (curtime == ((time_t) -1))
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
Packit |
8ea169 |
"Cannot get current time");
|
|
Packit |
8ea169 |
free(token);
|
|
Packit |
8ea169 |
return NULL;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
g_hash_table_insert(session->pv->p2s_tokens,
|
|
Packit |
8ea169 |
token,
|
|
Packit |
8ea169 |
GINT_TO_POINTER(curtime + duration));
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return token;
|
|
Packit |
8ea169 |
#undef SESSION_TOKEN_LENGTH
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
int abrt_p2_session_revoke_token(AbrtP2Session *session,
|
|
Packit |
8ea169 |
const char *token)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
return g_hash_table_remove(session->pv->p2s_tokens, token) ? 0 : 1;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static AbrtP2SessionAuthRequestRet abrt_p2_session_authorize_peer_with_token(
|
|
Packit |
8ea169 |
AbrtP2Session *session,
|
|
Packit |
8ea169 |
AbrtP2Session *peer_session,
|
|
Packit |
8ea169 |
const char *token,
|
|
Packit |
8ea169 |
GError **error)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
if (session->pv->p2s_state != ABRT_P2_SESSION_STATE_AUTH)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED,
|
|
Packit |
8ea169 |
"Not authorized session cannot pass authorization");
|
|
Packit |
8ea169 |
return ABRT_P2_SESSION_AUTHORIZE_FAILED;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (session->pv->p2s_uid != peer_session->pv->p2s_uid)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED,
|
|
Packit |
8ea169 |
"Session owners do not match");
|
|
Packit |
8ea169 |
return ABRT_P2_SESSION_AUTHORIZE_FAILED;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
const gpointer expire = g_hash_table_lookup(session->pv->p2s_tokens, token);
|
|
Packit |
8ea169 |
if (expire == NULL)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED,
|
|
Packit |
8ea169 |
"No such token");
|
|
Packit |
8ea169 |
return ABRT_P2_SESSION_AUTHORIZE_FAILED;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
const time_t curtime = time(NULL);
|
|
Packit |
8ea169 |
if (curtime == ((time_t) -1))
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
Packit |
8ea169 |
"Cannot get current time");
|
|
Packit |
8ea169 |
return ABRT_P2_SESSION_AUTHORIZE_FAILED;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (curtime > (time_t)(GPOINTER_TO_INT(expire)))
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED,
|
|
Packit |
8ea169 |
"Token has already expired");
|
|
Packit |
8ea169 |
return ABRT_P2_SESSION_AUTHORIZE_FAILED;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
g_hash_table_remove(session->pv->p2s_tokens, token);
|
|
Packit |
8ea169 |
abrt_p2_session_grant_authorization(peer_session);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
log_info("Granted authorization to peer session on '%s' bus",
|
|
Packit |
8ea169 |
peer_session->pv->p2s_caller);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return ABRT_P2_SESSION_AUTHORIZE_GRANTED;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static int abrt_p2_session_cmp_caller(AbrtP2Session *lhs, const char *bus_name)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
return strcmp(lhs->pv->p2s_caller, bus_name);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static AbrtP2SessionAuthRequestRet _abrt_p2_session_begin_auth(AbrtP2Session *session,
|
|
Packit |
8ea169 |
GVariant *parameters,
|
|
Packit |
8ea169 |
GList *peers,
|
|
Packit |
8ea169 |
GError **error)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
AbrtP2SessionAuthRequestRet ret = ABRT_P2_SESSION_AUTHORIZE_FAILED;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
GVariant *peer_bus = g_variant_lookup_value(parameters,
|
|
Packit |
8ea169 |
"problems2.peer-bus",
|
|
Packit |
8ea169 |
G_VARIANT_TYPE_STRING);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
GVariant *peer_token = g_variant_lookup_value(parameters,
|
|
Packit |
8ea169 |
"problems2.peer-token",
|
|
Packit |
8ea169 |
G_VARIANT_TYPE_STRING);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (!peer_bus && !peer_token)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
authorization_request_initialize(session, parameters);
|
|
Packit |
8ea169 |
ret = ABRT_P2_SESSION_AUTHORIZE_ACCEPTED;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
else if (peer_bus && peer_token)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
const gchar *bus = g_variant_get_string(peer_bus, NULL);
|
|
Packit |
8ea169 |
GList *tmp = g_list_find_custom(peers,
|
|
Packit |
8ea169 |
bus,
|
|
Packit |
8ea169 |
(GCompareFunc)abrt_p2_session_cmp_caller);
|
|
Packit |
8ea169 |
if (tmp == NULL)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
Packit |
8ea169 |
"No peer session for bus '%s'",
|
|
Packit |
8ea169 |
g_variant_get_string(peer_bus, NULL));
|
|
Packit |
8ea169 |
goto finito;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
AbrtP2Session *peer_session = (AbrtP2Session *)tmp->data;
|
|
Packit |
8ea169 |
const gchar *token = g_variant_get_string(peer_token, NULL);
|
|
Packit |
8ea169 |
ret = abrt_p2_session_authorize_peer_with_token(peer_session,
|
|
Packit |
8ea169 |
session,
|
|
Packit |
8ea169 |
token,
|
|
Packit |
8ea169 |
error);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
else /* if ((peer_bus && !peer_token) || (!peer_bus && peer_token)) */
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
Packit |
8ea169 |
"Invalid parameters peer-bus and peer-token.");
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
finito:
|
|
Packit |
8ea169 |
if (peer_bus != NULL)
|
|
Packit |
8ea169 |
g_variant_unref(peer_bus);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (peer_token != NULL)
|
|
Packit |
8ea169 |
g_variant_unref(peer_token);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return ret;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
AbrtP2SessionAuthRequestRet abrt_p2_session_authorize(AbrtP2Session *session,
|
|
Packit |
8ea169 |
GVariant *parameters,
|
|
Packit |
8ea169 |
GList *peers,
|
|
Packit |
8ea169 |
GError **error)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
switch(session->pv->p2s_state)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
case ABRT_P2_SESSION_STATE_INIT:
|
|
Packit |
8ea169 |
return _abrt_p2_session_begin_auth(session, parameters, peers, error);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
case ABRT_P2_SESSION_STATE_PENDING:
|
|
Packit |
8ea169 |
return ABRT_P2_SESSION_AUTHORIZE_PENDING;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
case ABRT_P2_SESSION_STATE_AUTH:
|
|
Packit |
8ea169 |
return ABRT_P2_SESSION_AUTHORIZE_GRANTED;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
default:
|
|
Packit |
8ea169 |
error_msg("BUG: %s: forgotten state -> %d", __func__, session->pv->p2s_state);
|
|
Packit |
8ea169 |
return ABRT_P2_SESSION_AUTHORIZE_FAILED;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
void abrt_p2_session_revoke_authorization(AbrtP2Session *session)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
if (session->pv->p2s_uid == 0)
|
|
Packit |
8ea169 |
return;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
switch(session->pv->p2s_state)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
case ABRT_P2_SESSION_STATE_AUTH:
|
|
Packit |
8ea169 |
change_state(session, ABRT_P2_SESSION_STATE_INIT);
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
case ABRT_P2_SESSION_STATE_PENDING:
|
|
Packit |
8ea169 |
g_cancellable_cancel(session->pv->p2s_auth_rq->cancellable);
|
|
Packit |
8ea169 |
change_state(session, ABRT_P2_SESSION_STATE_INIT);
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
case ABRT_P2_SESSION_STATE_INIT:
|
|
Packit |
8ea169 |
/* pass */
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
AbrtP2SessionAuthRequestRet abrt_p2_session_grant_authorization(AbrtP2Session *session)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
switch(session->pv->p2s_state)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
case ABRT_P2_SESSION_STATE_AUTH:
|
|
Packit |
8ea169 |
/* pass */
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
case ABRT_P2_SESSION_STATE_PENDING:
|
|
Packit |
8ea169 |
g_cancellable_cancel(session->pv->p2s_auth_rq->cancellable);
|
|
Packit |
8ea169 |
change_state(session, ABRT_P2_SESSION_STATE_AUTH);
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
case ABRT_P2_SESSION_STATE_INIT:
|
|
Packit |
8ea169 |
change_state(session, ABRT_P2_SESSION_STATE_AUTH);
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return ABRT_P2_SESSION_AUTHORIZE_GRANTED;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
uid_t abrt_p2_session_uid(AbrtP2Session *session)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
return session->pv->p2s_uid;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
const char *abrt_p2_session_caller(AbrtP2Session *session)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
return session->pv->p2s_caller;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
int abrt_p2_session_is_authorized(AbrtP2Session *session)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
return session->pv->p2s_state == ABRT_P2_SESSION_STATE_AUTH;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
int abrt_p2_session_check_sanity(AbrtP2Session *session,
|
|
Packit |
8ea169 |
const char *caller,
|
|
Packit |
8ea169 |
uid_t caller_uid,
|
|
Packit |
8ea169 |
GError **error)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
if (strcmp(session->pv->p2s_caller, caller) == 0 && session->pv->p2s_uid == caller_uid)
|
|
Packit |
8ea169 |
/* the session node is sane */
|
|
Packit |
8ea169 |
return 0;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
log_warning("Problems2 Session object does not belong to UID %d", caller_uid);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
Packit |
8ea169 |
"Your Problems2 Session is broken. Check system logs for more details.");
|
|
Packit |
8ea169 |
return -1;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
uint32_t abrt_p2_session_add_task(AbrtP2Session *session,
|
|
Packit |
8ea169 |
AbrtP2Task *task,
|
|
Packit |
8ea169 |
GError **error)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
if (session->pv->p2s_task_indexer == (UINT32_MAX - 1))
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
Packit |
8ea169 |
"Reached the limit of task per session.");
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return UINT32_MAX;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (abrt_p2_session_owns_task(session, task) == 0)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
Packit |
8ea169 |
"Task is already owned by the session");
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return UINT32_MAX;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
session->pv->p2s_tasks = g_list_prepend(session->pv->p2s_tasks, task);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return session->pv->p2s_task_indexer++;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
void abrt_p2_session_remove_task(AbrtP2Session *session,
|
|
Packit |
8ea169 |
AbrtP2Task *task,
|
|
Packit |
8ea169 |
GError **error)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
session->pv->p2s_tasks = g_list_remove(session->pv->p2s_tasks, task);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
GList *abrt_p2_session_tasks(AbrtP2Session *session)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
return session->pv->p2s_tasks;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
int abrt_p2_session_owns_task(AbrtP2Session *session,
|
|
Packit |
8ea169 |
AbrtP2Task *task)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
return !(g_list_find(session->pv->p2s_tasks, task));
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
int abrt_p2_session_tasks_count(AbrtP2Session *session)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
return g_list_length(session->pv->p2s_tasks);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static void abrt_p2_session_dispose_task(AbrtP2Task *task,
|
|
Packit |
8ea169 |
gint32 status)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
switch(status)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
case ABRT_P2_TASK_STATUS_STOPPED:
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
GError *local_error = NULL;
|
|
Packit |
8ea169 |
abrt_p2_task_cancel(task, &local_error);
|
|
Packit |
8ea169 |
if (local_error != NULL)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
error_msg("Task garbage collector failed to cancel task: %s",
|
|
Packit |
8ea169 |
local_error->message);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
g_error_free(local_error);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* In case of errors, this could cause problems, but I
|
|
Packit |
8ea169 |
* don't have better plan yet. */
|
|
Packit |
8ea169 |
log_debug("Disposed new/stopped task: %p", task);
|
|
Packit |
8ea169 |
g_object_unref(task);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
case ABRT_P2_TASK_STATUS_NEW:
|
|
Packit |
8ea169 |
log_debug("Disposed new task: %p", task);
|
|
Packit |
8ea169 |
g_object_unref(task);
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
case ABRT_P2_TASK_STATUS_FAILED:
|
|
Packit |
8ea169 |
log_debug("Disposed failed task: %p", task);
|
|
Packit |
8ea169 |
g_object_unref(task);
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
case ABRT_P2_TASK_STATUS_CANCELED:
|
|
Packit |
8ea169 |
log_debug("Disposed canceled task: %p", task);
|
|
Packit |
8ea169 |
g_object_unref(task);
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
case ABRT_P2_TASK_STATUS_DONE:
|
|
Packit |
8ea169 |
log_debug("Disposed done task: %p", task);
|
|
Packit |
8ea169 |
g_object_unref(task);
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
case ABRT_P2_TASK_STATUS_RUNNING:
|
|
Packit |
8ea169 |
error_msg("BUG: cannot dispose RUNNING task");
|
|
Packit |
8ea169 |
abort();
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static void abrt_p2_session_delayed_dispose_task(AbrtP2Task *task,
|
|
Packit |
8ea169 |
gint32 status,
|
|
Packit |
8ea169 |
gpointer user_data)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
if (status == ABRT_P2_TASK_STATUS_RUNNING)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
error_msg("BUG: task to dispose must not change state to RUNNING");
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
abort();
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
log_debug("Going to dispose delayed task: %p: %d",
|
|
Packit |
8ea169 |
task,
|
|
Packit |
8ea169 |
status);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
abrt_p2_session_dispose_task(task, status);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
void abrt_p2_session_clean_tasks(AbrtP2Session *session)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
GList *task = session->pv->p2s_tasks;
|
|
Packit |
8ea169 |
session->pv->p2s_tasks = NULL;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
while (task != NULL)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
AbrtP2Task *t = ABRT_P2_TASK(task->data);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
task = g_list_delete_link(task, task);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
const AbrtP2TaskStatus status = abrt_p2_task_status(t);
|
|
Packit |
8ea169 |
if (status != ABRT_P2_TASK_STATUS_RUNNING)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
abrt_p2_session_dispose_task(t, status);
|
|
Packit |
8ea169 |
continue;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
log_debug("Delaying disposal of running task: %p", t);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
g_signal_connect(t,
|
|
Packit |
8ea169 |
"status-changed",
|
|
Packit |
8ea169 |
G_CALLBACK(abrt_p2_session_delayed_dispose_task),
|
|
Packit |
8ea169 |
NULL);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
GError *local_error = NULL;
|
|
Packit |
8ea169 |
abrt_p2_task_cancel(t, &local_error);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (local_error != NULL)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
error_msg("Task garbage collector failed to cancel running task: %s",
|
|
Packit |
8ea169 |
local_error->message);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
g_error_free(local_error);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
}
|