---
 .gitignore                                |    1 +
 abrt.spec.in                              |   22 +-
 configure.ac                              |    3 +
 po/POTFILES.in                            |    2 +-
 src/Makefile.am                           |    2 +-
 src/daemon/Makefile.am                    |   26 +--
 src/daemon/abrt-dbus.c                    |  536 -------------------------
 src/daemon/com.redhat.abrt.service        |    7 -
 src/daemon/dbus-abrt.conf                 |   25 --
 src/dbus/Makefile.am                      |   35 ++
 src/dbus/abrt-dbus.c                      |  609 +++++++++++++++++++++++++++++
 src/dbus/abrt-polkit.c                    |  102 +++++
 src/dbus/abrt-polkit.h                    |   39 ++
 src/dbus/abrt_polkit.policy               |   28 ++
 src/dbus/dbus-abrt.conf                   |   25 ++
 src/dbus/org.freedesktop.problems.service |    7 +
 src/include/Makefile.am                   |    3 +-
 src/include/abrt-dbus.h                   |    8 +
 18 files changed, 881 insertions(+), 599 deletions(-)
 delete mode 100644 src/daemon/abrt-dbus.c
 delete mode 100644 src/daemon/com.redhat.abrt.service
 delete mode 100644 src/daemon/dbus-abrt.conf
 create mode 100644 src/dbus/Makefile.am
 create mode 100644 src/dbus/abrt-dbus.c
 create mode 100644 src/dbus/abrt-polkit.c
 create mode 100644 src/dbus/abrt-polkit.h
 create mode 100644 src/dbus/abrt_polkit.policy
 create mode 100644 src/dbus/dbus-abrt.conf
 create mode 100644 src/dbus/org.freedesktop.problems.service
 create mode 100644 src/include/abrt-dbus.h

diff --git a/.gitignore b/.gitignore
index 1388141..e354997 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@ src/daemon/abrt-server
 src/daemon/abrtd
 src/daemon/abrt-handle-event
 src/daemon/abrt-dbus
+src/dbus/abrt-dbus
 src/gui-gtk/abrt-gui
 src/plugins/abrt-action-analyze-backtrace
 src/plugins/abrt-action-analyze-c
diff --git a/abrt.spec.in b/abrt.spec.in
index 5cdf644..d619c19 100644
--- a/abrt.spec.in
+++ b/abrt.spec.in
@@ -198,6 +198,18 @@ Provides: bug-buddy
 %description desktop
 Virtual package to make easy default installation on desktop environments.
 
+%package dbus
+Summary: ABRT DBus service
+Group: Application/System
+Requires: %{name} = %{version}-%{release}
+Requires: libreport
+BuildRequires: polkit-devel
+
+%description dbus
+ABRT DBus service which provides org.freedesktop.problems API on dbus and
+uses PolicyKit to authorize to access the problem data.
+
+
 %prep
 %setup -q
 
@@ -438,7 +450,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null 
|| :
 %{_initrddir}/abrtd
 %endif
 %{_sbindir}/abrtd
-%{_sbindir}/abrt-dbus
 %{_sbindir}/abrt-server
 %{_libexecdir}/abrt-handle-event
 %{_bindir}/abrt-handle-upload
@@ -448,7 +459,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null 
|| :
 %config(noreplace) %{_sysconfdir}/%{name}/abrt-action-save-package-data.conf
 %config(noreplace) %{_sysconfdir}/%{name}/gpg_keys
 %config(noreplace) %{_sysconfdir}/libreport/events.d/abrt_event.conf
-%config(noreplace) %{_sysconfdir}/dbus-1/system.d/dbus-abrt.conf
 %config(noreplace) %{_sysconfdir}/libreport/events.d/smart_event.conf
 %config(noreplace) %{_sysconfdir}/libreport/events.d/smolt_event.conf
 %dir %attr(0755, abrt, abrt) %{_localstatedir}/spool/%{name}
@@ -469,7 +479,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null 
|| :
 %{_mandir}/man5/abrt.conf.5.gz
 %{_mandir}/man5/abrt-action-save-package-data.conf.5.gz
 # {_mandir}/man5/pyhook.conf.5.gz
-%{_datadir}/dbus-1/system-services/com.redhat.abrt.service
 
 %files libs
 %defattr(-,root,root,-)
@@ -594,6 +603,13 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor 
&>/dev/null || :
 %files desktop
 %defattr(-,root,root,-)
 
+%files dbus
+%defattr(-,root,root,-)
+%{_sbindir}/abrt-dbus
+%config(noreplace) %{_sysconfdir}/dbus-1/system.d/dbus-abrt.conf
+%{_datadir}/dbus-1/system-services/org.freedesktop.problems.service
+%{_datadir}/polkit-1/actions/abrt_polkit.policy
+
 %changelog
 * Wed Mar 16 2011 Jiri Moskovcak <[email protected]> 2.0.0-1
 - update to the latest upstream version
diff --git a/configure.ac b/configure.ac
index 4391239..987cacd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -71,12 +71,14 @@ PKG_CHECK_MODULES([NSS], [nss])
 PKG_CHECK_MODULES([BTPARSER], [btparser])
 PKG_CHECK_MODULES([LIBREPORT], [libreport])
 PKG_CHECK_MODULES([LIBREPORT_GTK], [libreport-gtk])
+PKG_CHECK_MODULES([POLKIT], [polkit-gobject-1])
 # Just PKG_CHECK_MODULES([PYTHON], [python]) works only with python2.7+
 # Below, if python is not found, we set up for python2.6 w/o checking:
 PKG_CHECK_MODULES([PYTHON], [python],,[
     PYTHON_LIBS='-L/usr/lib64 -lpython2.6'
     PYTHON_CFLAGS='-I/usr/include/python2.6'
 ])
+PKG_CHECK_MODULES([GIO], [gio-2.0])
 
 AC_ARG_ENABLE([dupcheck-fingerprint],
         AS_HELP_STRING([--enable-dupcheck-fingerprint], [enable function 
fingerprinting for duplicate checking (x86_64 only)]),
@@ -129,6 +131,7 @@ AC_CONFIG_FILES([
        src/applet/Makefile
        src/gui-gtk/Makefile
        src/cli/Makefile
+       src/dbus/Makefile
        src/plugins/abrt-action-install-debuginfo
        src/plugins/abrt-action-analyze-vmcore
        po/Makefile.in
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1e9e5cd..254518a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -5,7 +5,7 @@ src/applet/abrt-applet.desktop.in
 src/applet/applet.c
 src/daemon/abrt-action-save-package-data.c
 src/daemon/abrt-server.c
-src/daemon/abrt-dbus.c
+src/dbus/abrt-dbus.c
 src/daemon/abrtd.c
 src/daemon/abrt-handle-event.c
 src/gui-gtk/abrt.desktop.in
diff --git a/src/Makefile.am b/src/Makefile.am
index ab95ef7..2198f3c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1 +1 @@
-SUBDIRS = include lib hooks daemon applet gui-gtk plugins cli
+SUBDIRS = include lib hooks daemon applet gui-gtk plugins cli dbus
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index bed3c44..46a4517 100644
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
@@ -11,8 +11,7 @@ bin_PROGRAMS = \
 
 sbin_PROGRAMS = \
     abrtd \
-    abrt-server \
-    abrt-dbus
+    abrt-server
 
 libexec_PROGRAMS = abrt-handle-event
 
@@ -44,24 +43,6 @@ abrt_server_LDADD = \
     ../lib/libabrt.la \
     $(LIBREPORT_LIBS)
 
-abrt_dbus_SOURCES = \
-    abrt-dbus.c
-abrt_dbus_CPPFLAGS = \
-    -I$(srcdir)/../include \
-    -I$(srcdir)/../lib \
-    -DVAR_RUN=\"$(VAR_RUN)\" \
-    $(GLIB_CFLAGS) \
-    $(DBUS_CFLAGS) \
-    $(LIBREPORT_CFLAGS) \
-    -D_GNU_SOURCE \
-    -Wall -Wwrite-strings \
-    -Werror
-abrt_dbus_LDADD = \
-    $(DBUS_LIBS) \
-    ../lib/libabrt.la \
-    $(LIBREPORT_LIBS) \
-    -labrt_dbus
-
 abrt_handle_event_SOURCES = \
     abrt-handle-event.c
 abrt_handle_event_CPPFLAGS = \
@@ -93,17 +74,12 @@ abrt_action_save_package_data_LDADD = \
     $(LIBREPORT_LIBS) \
     ../lib/libabrt.la
 
-dbusabrtconfdir = ${sysconfdir}/dbus-1/system.d/
-dist_dbusabrtconf_DATA = dbus-abrt.conf
-
 daemonconfdir = $(CONF_DIR)
 dist_daemonconf_DATA = \
     abrt.conf \
     abrt-action-save-package-data.conf \
     gpg_keys
 
-comredhatabrtservicedir = ${datadir}/dbus-1/system-services
-dist_comredhatabrtservice_DATA = com.redhat.abrt.service
 EXTRA_DIST = abrt-handle-upload
 
 DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
diff --git a/src/daemon/abrt-dbus.c b/src/daemon/abrt-dbus.c
deleted file mode 100644
index ee53ba9..0000000
--- a/src/daemon/abrt-dbus.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
-    Copyright (C) 2011  ABRT team
-    Copyright (C) 2011  RedHat Inc
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-#include <syslog.h>
-#include <dbus/dbus.h>
-#include <internal_abrt_dbus.h>
-#include "libabrt.h"
-
-/* I want to use -Werror, but gcc-4.4 throws a curveball:
- * "warning: ignoring return value of 'ftruncate', declared with attribute 
warn_unused_result"
- * and (void) cast is not enough to shut it up! Oh God...
- */
-#define IGNORE_RESULT(func_call) do { if (func_call) /* nothing */; } while (0)
-
-
-#define ABRTD_DBUS_NAME  "com.redhat.abrt"
-#define ABRTD_DBUS_PATH  "/com/redhat/abrt"
-#define ABRTD_DBUS_IFACE "com.redhat.abrt"
-
-
-static volatile sig_atomic_t s_sig_caught;
-static int s_signal_pipe[2];
-static int s_signal_pipe_write = -1;
-static unsigned s_timeout;
-static bool s_exiting;
-
-
-static void send_flush_and_unref(DBusMessage* msg)
-{
-    if (!g_dbus_conn)
-    {
-        /* Not logging this, it may recurse */
-        return;
-    }
-    if (!dbus_connection_send(g_dbus_conn, msg, NULL /* &serial */))
-        error_msg_and_die("Error sending DBus message");
-    dbus_connection_flush(g_dbus_conn);
-    VERB3 log("DBus message sent");
-    dbus_message_unref(msg);
-}
-
-/*
- * DBus call handlers
- */
-
-static GList* scan_directory(const char *path)
-{
-    GList *list = NULL;
-
-    DIR *dp = opendir(path);
-    if (!dp)
-    {
-        /* We don't want to yell if, say, $HOME/.abrt/spool doesn't exist */
-        //perror_msg("Can't open directory '%s'", path);
-        return list;
-    }
-
-    struct dirent *dent;
-    while ((dent = readdir(dp)) != NULL)
-    {
-        if (dot_or_dotdot(dent->d_name))
-            continue; /* skip "." and ".." */
-
-        char *full_name = concat_path_file(path, dent->d_name);
-        struct stat statbuf;
-        if (stat(full_name, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
-        {
-            /* Silently ignore *any* errors, not only EACCES.
-             * We saw "lock file is locked by process PID" error
-             * when we raced with wizard.
-             */
-            int sv_logmode = logmode;
-            logmode = 0;
-            struct dump_dir *dd = dd_opendir(full_name, DD_OPEN_READONLY | 
DD_FAIL_QUIETLY_EACCES);
-            logmode = sv_logmode;
-            if (dd)
-            {
-                list = g_list_prepend(list, full_name);
-                full_name = NULL;
-                dd_close(dd);
-            }
-        }
-        free(full_name);
-    }
-    closedir(dp);
-
-    /* Why reverse?
-     * Because N*prepend+reverse is faster than N*append
-     */
-    return g_list_reverse(list);
-}
-
-/* To test from command line:
- * dbus-send --system --type=method_call --print-reply --dest=com.redhat.abrt \
- *     /com/redhat/abrt com.redhat.abrt.GetListOfProblems
- */
-static int handle_GetListOfProblems(DBusMessage* call, DBusMessage* reply)
-{
-    DBusMessageIter out_iter;
-    dbus_message_iter_init_append(reply, &out_iter);
-
-    GList *list = scan_directory(g_settings_dump_location);
-
-    /* Store the array */
-    DBusMessageIter sub_iter;
-    if (!dbus_message_iter_open_container(&out_iter, DBUS_TYPE_ARRAY, "s", 
&sub_iter))
-        die_out_of_memory();
-    while (list)
-    {
-        store_string(&sub_iter, (char*)list->data);
-        free(list->data);
-        list = g_list_delete_link(list, list);
-    }
-    if (!dbus_message_iter_close_container(&out_iter, &sub_iter))
-        die_out_of_memory();
-
-    /* Send reply */
-    send_flush_and_unref(reply);
-    return 0;
-}
-
-/*
- * Glib integration machinery
- */
-
-/* Callback: "a message is received to a registered object path" */
-static DBusHandlerResult message_received(DBusConnection* conn, DBusMessage* 
msg, void* data)
-{
-    const char* member = dbus_message_get_member(msg);
-    VERB1 log("%s(method:'%s')", __func__, member);
-
-    //set_client_name(dbus_message_get_sender(msg));
-
-    DBusMessage* reply = dbus_message_new_method_return(msg);
-    int r = -1;
-    if (strcmp(member, "GetListOfProblems") == 0)
-        r = handle_GetListOfProblems(msg, reply);
-// NB: C++ binding also handles "Introspect" method, which returns a string.
-// It was sending "dummy" introspection answer whick looks like this:
-// "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 
1.0//EN\"\n"
-// "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\";>\n"
-// "<node>\n"
-// "</node>\n"
-// Apart from a warning from abrt-gui, just sending error back works as well.
-// NB2: we may want to handle "Disconnected" here too.
-
-    if (r < 0)
-    {
-        /* handle_XXX experienced an error (and did not send any reply) */
-        dbus_message_unref(reply);
-        if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL)
-        {
-            /* Create and send error reply */
-            reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "not 
supported");
-            if (!reply)
-                die_out_of_memory();
-            send_flush_and_unref(reply);
-        }
-    }
-
-    //set_client_name(NULL);
-
-    return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-static void handle_dbus_err(bool error_flag, DBusError *err)
-{
-    if (dbus_error_is_set(err))
-    {
-        error_msg("dbus error: %s", err->message);
-        /* dbus_error_free(&err); */
-        error_flag = true;
-    }
-    if (!error_flag)
-        return;
-    error_msg_and_die(
-            "Error requesting DBus name %s, possible reasons: "
-            "abrt run by non-root; dbus config is incorrect; "
-            "or dbus daemon needs to be restarted to reload dbus config",
-            ABRTD_DBUS_NAME);
-}
-
-static int init_dbus(void)
-{
-    DBusConnection* conn;
-    DBusError err;
-
-    dbus_error_init(&err);
-    VERB3 log("dbus_bus_get");
-    conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
-    handle_dbus_err(conn == NULL, &err);
-    // dbus api says:
-    // "If dbus_bus_get obtains a new connection object never before returned
-    // from dbus_bus_get(), it will call 
dbus_connection_set_exit_on_disconnect(),
-    // so the application will exit if the connection closes. You can undo this
-    // by calling dbus_connection_set_exit_on_disconnect() yourself after you 
get
-    // the connection."
-    // ...
-    // "When a connection is disconnected, you are guaranteed to get a signal
-    // "Disconnected" from the interface DBUS_INTERFACE_LOCAL, path 
DBUS_PATH_LOCAL"
-    //
-    // dbus-daemon drops connections if it recvs a malformed message
-    // (we actually observed this when we sent bad UTF-8 string).
-    // Currently, in this case abrtd just exits with exit code 1.
-    // (symptom: last two log messages are "abrtd: remove_watch()")
-    // If we want to have better logging or other nontrivial handling,
-    // here we need to do:
-    //
-    //dbus_connection_set_exit_on_disconnect(conn, FALSE);
-    //dbus_connection_add_filter(conn, handle_message, NULL, NULL);
-    //
-    // and need to code up handle_message to check for "Disconnected" dbus 
signal
-
-    /* Also sets g_dbus_conn to conn. */
-    attach_dbus_conn_to_glib_main_loop(conn, "/com/redhat/abrt", 
message_received);
-
-    VERB3 log("dbus_bus_request_name");
-    int rc = dbus_bus_request_name(conn, ABRTD_DBUS_NAME, 
DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
-//maybe check that r == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER instead?
-    handle_dbus_err(rc < 0, &err);
-    VERB3 log("dbus init done");
-
-    /* dbus_bus_request_name can already read some data. For example,
-     * if we were autostarted, the call which caused autostart arrives
-     * at this moment. Thus while dbus fd hasn't any data anymore,
-     * dbus library can buffer a message or two.
-     * If we don't do this, the data won't be processed
-     * until next dbus data arrives.
-     */
-    int cnt = 10;
-    while (dbus_connection_dispatch(conn) != DBUS_DISPATCH_COMPLETE && --cnt)
-        VERB3 log("processed initial buffered dbus message");
-
-    return 0;
-}
-
-static void deinit_dbus(void)
-{
-    if (g_dbus_conn != NULL)
-    {
-        dbus_connection_unref(g_dbus_conn);
-        g_dbus_conn = NULL;
-    }
-}
-
-/*
- * Signal pipe handling
- */
-
-static void handle_signal(int signo)
-{
-    int save_errno = errno;
-
-    // Enable for debugging only, malloc/printf are unsafe in signal handlers
-    //VERB3 log("Got signal %d", signo);
-
-    uint8_t sig_caught;
-    s_sig_caught = sig_caught = signo;
-    /* Using local copy of s_sig_caught so that concurrent signal
-     * won't change it under us */
-    if (s_signal_pipe_write >= 0)
-        IGNORE_RESULT(write(s_signal_pipe_write, &sig_caught, 1));
-
-    errno = save_errno;
-}
-
-/* Signal pipe handler */
-static gboolean handle_signal_cb(GIOChannel *gio, GIOCondition condition, 
gpointer ptr_unused)
-{
-    uint8_t signo;
-    gsize len = 0;
-    g_io_channel_read_chars(gio, (void*) &signo, 1, &len, NULL);
-    if (len == 1)
-    {
-        /* we did receive a signal */
-        VERB3 log("Got signal %d through signal pipe", signo);
-        s_exiting = 1;
-    }
-    return TRUE; /* "please don't remove this event" */
-}
-
-
-static void start_syslog_logging(void)
-{
-    /* Open stdin to /dev/null */
-    xmove_fd(xopen("/dev/null", O_RDWR), STDIN_FILENO);
-    /* We must not leave fds 0,1,2 closed.
-     * Otherwise fprintf(stderr) dumps messages into random fds, etc. */
-    xdup2(STDIN_FILENO, STDOUT_FILENO);
-    xdup2(STDIN_FILENO, STDERR_FILENO);
-    openlog(g_progname, 0, LOG_DAEMON);
-    logmode = LOGMODE_SYSLOG;
-    putenv((char*)"ABRT_SYSLOG=1");
-}
-
-/* Run main loop with idle timeout.
- * Basically, almost like glib's g_main_run(loop)
- */
-static void run_main_loop(GMainLoop *loop)
-{
-    time_t cur_time = time(NULL);
-    GMainContext *context = g_main_loop_get_context(loop);
-    int fds_size = 0;
-    GPollFD *fds = NULL;
-
-    while (!s_exiting)
-    {
-        gboolean some_ready;
-        gint max_priority;
-        gint timeout;
-        gint nfds;
-
-        some_ready = g_main_context_prepare(context, &max_priority);
-        if (some_ready)
-            g_main_context_dispatch(context);
-
-        while (1)
-        {
-            nfds = g_main_context_query(context, max_priority, &timeout, fds, 
fds_size);
-            if (nfds <= fds_size)
-                break;
-            fds_size = nfds + 16; /* +16: optimizing realloc frequency */
-            fds = (GPollFD *)xrealloc(fds, fds_size * sizeof(fds[0]));
-        }
-
-        if (s_timeout != 0)
-            alarm(s_timeout);
-        g_poll(fds, nfds, timeout);
-        if (s_timeout != 0)
-            alarm(0);
-
-        time_t new_time = time(NULL);
-        if (cur_time != new_time)
-        {
-            cur_time = new_time;
-            load_abrt_conf();
-//TODO: react to changes in g_settings_sWatchCrashdumpArchiveDir
-        }
-
-        some_ready = g_main_context_check(context, max_priority, fds, nfds);
-        if (some_ready)
-            g_main_context_dispatch(context);
-    }
-
-    free(fds);
-    g_main_context_unref(context);
-}
-
-int main(int argc, char** argv)
-{
-    /* I18n */
-    setlocale(LC_ALL, "");
-#if ENABLE_NLS
-    bindtextdomain(PACKAGE, LOCALEDIR);
-    textdomain(PACKAGE);
-#endif
-
-    abrt_init(argv);
-
-    int parent_pid = getpid();
-
-    const char *program_usage_string = _(
-        "& [options]"
-    );
-    enum {
-        OPT_v = 1 << 0,
-        OPT_d = 1 << 1,
-        OPT_s = 1 << 2,
-        OPT_t = 1 << 3,
-    };
-    /* Keep enum above and order of options below in sync! */
-    struct options program_options[] = {
-        OPT__VERBOSE(&g_verbose),
-        OPT_BOOL(   'd', NULL, NULL      , _("Do not daemonize")),
-        OPT_BOOL(   's', NULL, NULL      , _("Log to syslog even with -d")),
-        OPT_INTEGER('t', NULL, &s_timeout, _("Exit after NUM seconds of 
inactivity")),
-        OPT_END()
-    };
-    unsigned opts = parse_opts(argc, argv, program_options, 
program_usage_string);
-
-    export_abrt_envvars(0);
-
-    /* When dbus daemon starts us, it doesn't set PATH
-     * (I saw it set only DBUS_STARTER_ADDRESS and DBUS_STARTER_BUS_TYPE).
-     * In this case, set something sane:
-     */
-    const char *env_path = getenv("PATH");
-    if (!env_path || !env_path[0])
-        putenv((char*)"PATH=/usr/sbin:/usr/bin:/sbin:/bin");
-
-    unsetenv("ABRT_SYSLOG");
-    msg_prefix = g_progname; /* for log(), error_msg() and such */
-
-    if (getuid() != 0)
-        error_msg_and_die("Must be run as root");
-
-    if (opts & OPT_s)
-        start_syslog_logging();
-
-    xpipe(s_signal_pipe);
-    close_on_exec_on(s_signal_pipe[0]);
-    close_on_exec_on(s_signal_pipe[1]);
-    ndelay_on(s_signal_pipe[0]); /* I/O should not block - */
-    ndelay_on(s_signal_pipe[1]); /* especially writes! they happen in signal 
handler! */
-    signal(SIGTERM, handle_signal);
-    signal(SIGINT,  handle_signal);
-    if (s_timeout != 0)
-        signal(SIGALRM, handle_signal);
-
-    /* Daemonize unless -d */
-    if (!(opts & OPT_d))
-    {
-        /* forking to background */
-        pid_t pid = fork();
-        if (pid < 0)
-        {
-            perror_msg_and_die("fork");
-        }
-        if (pid > 0)
-        {
-            /* Parent */
-            /* Wait for child to notify us via SIGTERM that it feels ok */
-            int i = 20; /* 2 sec */
-            while (s_sig_caught == 0 && --i)
-            {
-                usleep(100 * 1000);
-            }
-            if (s_sig_caught == SIGTERM)
-            {
-                exit(0);
-            }
-            if (s_sig_caught)
-            {
-                error_msg_and_die("Failed to start: got sig %d", s_sig_caught);
-            }
-            error_msg_and_die("Failed to start: timeout waiting for child");
-        }
-        /* Child (daemon) continues */
-        setsid(); /* never fails */
-        if (g_verbose == 0 && logmode != LOGMODE_SYSLOG)
-            start_syslog_logging();
-    }
-
-    GMainLoop *pMainloop = NULL;
-    GIOChannel *channel_signal = NULL;
-    guint channel_signal_event_id = 0;
-
-    /* Initialization */
-
-    VERB1 log("Loading settings");
-    if (load_abrt_conf() != 0)
-        goto init_error;
-
-    VERB1 log("Creating glib main loop");
-    pMainloop = g_main_loop_new(NULL, FALSE);
-
-    /* Add an event source which waits for INT/TERM signal */
-    VERB1 log("Adding signal pipe watch to glib main loop");
-    channel_signal = g_io_channel_unix_new(s_signal_pipe[0]);
-    channel_signal_event_id = g_io_add_watch(channel_signal,
-                                             G_IO_IN,
-                                             handle_signal_cb,
-                                             NULL);
-
-    /* Note: this already may process a few dbus messages,
-     * therefore it should be the last thing to initialize.
-     */
-    VERB1 log("Initializing dbus");
-    if (init_dbus() != 0)
-        goto init_error;
-
-    /* Inform parent that we initialized ok */
-    if (!(opts & OPT_d))
-    {
-        VERB1 log("Signalling parent");
-        kill(parent_pid, SIGTERM);
-        if (logmode != LOGMODE_SYSLOG)
-            start_syslog_logging();
-    }
-
-    /* Only now we want signal pipe to work */
-    s_signal_pipe_write = s_signal_pipe[1];
-
-    /* Enter the event loop */
-    log("Init complete, entering main loop");
-    run_main_loop(pMainloop);
-
- cleanup:
-    /* Error or INT/TERM. Clean up, in reverse order.
-     * Take care to not undo things we did not do.
-     */
-
-    if (channel_signal_event_id > 0)
-        g_source_remove(channel_signal_event_id);
-    if (channel_signal)
-        g_io_channel_unref(channel_signal);
-
-    deinit_dbus();
-
-    if (pMainloop)
-        g_main_loop_unref(pMainloop);
-
-    free_abrt_conf_data();
-
-    /* Exiting */
-    if (s_sig_caught && s_sig_caught != SIGALRM)
-    {
-        error_msg("Got signal %d, exiting", s_sig_caught);
-        signal(s_sig_caught, SIG_DFL);
-        raise(s_sig_caught);
-    }
-    error_msg_and_die("Exiting");
-
- init_error:
-    /* Initialization error */
-    error_msg("Error while initializing daemon");
-    /* Inform parent that initialization failed */
-    if (!(opts & OPT_d))
-        kill(parent_pid, SIGINT);
-    goto cleanup;
-}
diff --git a/src/daemon/com.redhat.abrt.service 
b/src/daemon/com.redhat.abrt.service
deleted file mode 100644
index afcb9a2..0000000
--- a/src/daemon/com.redhat.abrt.service
+++ /dev/null
@@ -1,7 +0,0 @@
-[D-BUS Service]
-Name=com.redhat.abrt
-# For testing, you may use -t5 to use small timeout of 5 seconds.
-# This will make "abrtd exited while clients existed but were idle"
-# situations easier to trigger
-Exec=/usr/sbin/abrt-dbus -ds -t133
-User=root
diff --git a/src/daemon/dbus-abrt.conf b/src/daemon/dbus-abrt.conf
deleted file mode 100644
index 11b2a11..0000000
--- a/src/daemon/dbus-abrt.conf
+++ /dev/null
@@ -1,25 +0,0 @@
-<!-- This configuration file specifies the required security policies
-     for abrt core daemon to work. -->
-
-<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 
1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd";>
-<busconfig>
-
-  <!-- ../system.conf have denied everything, so we just punch some holes -->
-
-  <policy user="root">
-    <allow own="com.redhat.abrt"/>
-    <allow send_destination="com.redhat.abrt"/>
-    <allow send_interface="com.redhat.abrt"/>
-  </policy>
-
-  <policy at_console="true">
-    <allow send_destination="com.redhat.abrt"/>
-  </policy>
-
-  <!-- Allow anyone to invoke methods on abrt server -->
-  <policy context="default">
-    <allow send_destination="com.redhat.abrt"/>
-  </policy>
-
-</busconfig>
diff --git a/src/dbus/Makefile.am b/src/dbus/Makefile.am
new file mode 100644
index 0000000..5f29c71
--- /dev/null
+++ b/src/dbus/Makefile.am
@@ -0,0 +1,35 @@
+sbin_PROGRAMS = \
+    abrt-dbus
+
+abrt_dbus_SOURCES = \
+    abrt-dbus.c \
+    abrt-polkit.c \
+    abrt-polkit.h
+abrt_dbus_CPPFLAGS = \
+    -I$(srcdir)/../include \
+    -I$(srcdir)/../lib \
+    -DVAR_RUN=\"$(VAR_RUN)\" \
+    $(GIO_CFLAGS) \
+    $(DBUS_CFLAGS) \
+    $(LIBREPORT_CFLAGS) \
+    $(POLKIT_CFLAGS) \
+    -D_GNU_SOURCE \
+    -Wall -Wwrite-strings \
+    -Werror
+abrt_dbus_LDADD = \
+    $(GIO_LIBS) \
+    ../lib/libabrt.la \
+    $(LIBREPORT_LIBS) \
+    $(POLKIT_LIBS) \
+    -labrt_dbus
+
+DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
+
+polkitconfdir = ${datadir}/polkit-1/actions
+dist_polkitconf_DATA = abrt_polkit.policy
+
+dbusabrtconfdir = ${sysconfdir}/dbus-1/system.d/
+dist_dbusabrtconf_DATA = dbus-abrt.conf
+
+orgfreedesktopproblemsservicedir = ${datadir}/dbus-1/system-services
+dist_orgfreedesktopproblemsservice_DATA = org.freedesktop.problems.service
diff --git a/src/dbus/abrt-dbus.c b/src/dbus/abrt-dbus.c
new file mode 100644
index 0000000..4899285
--- /dev/null
+++ b/src/dbus/abrt-dbus.c
@@ -0,0 +1,609 @@
+#include <gio/gio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include "libabrt.h"
+#include "abrt-polkit.h"
+#include "abrt-dbus.h"
+
+GMainLoop *loop;
+guint g_timeout;
+static unsigned s_timeout;
+
+/* 
----------------------------------------------------------------------------------------------------
 */
+
+static GDBusNodeInfo *introspection_data = NULL;
+
+/* Introspection data for the service we are exporting */
+static const gchar introspection_xml[] =
+  "<node>"
+  "  <interface name='"ABRT_DBUS_IFACE"'>"
+  "    <method name='GetProblems'>"
+  "      <arg type='s' name='directory' direction='in'/>"
+  "      <arg type='as' name='response' direction='out'/>"
+  "    </method>"
+  "    <method name='GetAllProblems'>"
+  "      <arg type='s' name='directory' direction='in'/>"
+  "      <arg type='as' name='response' direction='out'/>"
+  "    </method>"
+  "    <method name='GetInfo'>"
+  "      <arg type='s' name='problem_dir' direction='in'/>"
+  "      <arg type='a{ss}' name='response' direction='out'/>"
+  "    </method>"
+  "    <method name='ChownProblemDir'>"
+  "      <arg type='s' name='problem_dir' direction='in'/>"
+  "    </method>"
+  "    <method name='Quit' />"
+  "  </interface>"
+  "</node>";
+
+/* 
----------------------------------------------------------------------------------------------------
 */
+
+/* forward */
+static gboolean on_timeout_cb(gpointer user_data);
+
+static void reset_timeout()
+{
+    //FIXME: reset timer on every call
+    if (g_timeout > 0)
+    {
+        VERB2 log("Removing timeout");
+        g_source_remove(g_timeout);
+    }
+    VERB2 log("Setting a new timeout");
+    g_timeout = g_timeout_add_seconds(s_timeout, on_timeout_cb, NULL);
+}
+
+uid_t get_caller_uid(GDBusConnection *connection, const char *caller, GError 
*error)
+{
+    guint caller_uid;
+
+    GDBusProxy * proxy = g_dbus_proxy_new_sync(connection,
+                                     G_DBUS_PROXY_FLAGS_NONE,
+                                     NULL,
+                                     "org.freedesktop.DBus",
+                                     "/org/freedesktop/DBus",
+                                     "org.freedesktop.DBus",
+                                     NULL,
+                                     &error);
+
+    GVariant *result = g_dbus_proxy_call_sync(proxy,
+                                     "GetConnectionUnixUser",
+                                     g_variant_new ("(s)", caller),
+                                     G_DBUS_CALL_FLAGS_NONE,
+                                     -1,
+                                     NULL,
+                                     &error);
+
+    if (result == NULL) {
+        /* this value shouldn't be used, beacuse error is set,
+         * but return 99 -> nobody just to be sure
+         */
+        return 99;
+    }
+
+    g_variant_get(result, "(u)", &caller_uid);
+    g_variant_unref(result);
+
+    VERB2 log("Caller uid: %i", caller_uid);
+    return caller_uid;
+}
+
+bool uid_in_group(uid_t uid, gid_t gid)
+{
+    char **tmp;
+    struct passwd *pwd = getpwuid(uid);
+    if (pwd && (pwd->pw_gid == gid))
+        return TRUE;
+
+    struct group *grp = getgrgid(gid);
+    if (pwd && grp && grp->gr_mem)
+    {
+        for (tmp = grp->gr_mem; *tmp != NULL; tmp++)
+        {
+            if (g_strcmp0(*tmp, pwd->pw_name) == 0)
+            {
+                VERB3 log("user %s belongs to group: %s",  pwd->pw_name, 
grp->gr_name);
+                return TRUE;
+            }
+        }
+    }
+    VERB2 log("WARN: user %s DOESN'T belong to group: %s",  pwd->pw_name, 
grp->gr_name);
+    return FALSE;
+}
+
+static GList* scan_directory(const char *path, uid_t caller_uid)
+{
+    GList *list = NULL;
+
+    DIR *dp = opendir(path);
+    if (!dp)
+    {
+        /* We don't want to yell if, say, $HOME/.abrt/spool doesn't exist */
+        //perror_msg("Can't open directory '%s'", path);
+        return list;
+    }
+
+    struct dirent *dent;
+    while ((dent = readdir(dp)) != NULL)
+    {
+        if (dot_or_dotdot(dent->d_name))
+            continue; /* skip "." and ".." */
+
+        char *full_name = concat_path_file(path, dent->d_name);
+        struct stat statbuf;
+        if (stat(full_name, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
+        {
+            /* Silently ignore *any* errors, not only EACCES.
+             * We saw "lock file is locked by process PID" error
+             * when we raced with wizard.
+             */
+            int sv_logmode = logmode;
+            logmode = 0;
+            struct dump_dir *dd = dd_opendir(full_name, DD_OPEN_READONLY | 
DD_FAIL_QUIETLY_EACCES);
+            logmode = sv_logmode;
+            /* or we could just setuid?
+             - but it would require locking, because we want to setuid back 
before we server another request..
+            */
+            if (dd && (caller_uid == 0 || statbuf.st_mode & S_IROTH || 
uid_in_group(caller_uid, statbuf.st_gid)))
+            {
+                list = g_list_prepend(list, full_name);
+                full_name = NULL;
+            }
+            dd_close(dd); //doesn't fail even if dd == NULL
+        }
+        free(full_name);
+    }
+    closedir(dp);
+
+    /* Why reverse?
+     * Because N*prepend+reverse is faster than N*append
+     */
+    return g_list_reverse(list);
+}
+
+GVariant *get_problem_dirs_for_uid(uid_t uid, const char *dump_location)
+{
+    GList *dirs = scan_directory(dump_location, uid);
+
+    GVariantBuilder *builder;
+    builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+    while (dirs)
+    {
+        g_variant_builder_add(builder, "s", (char*)dirs->data);
+        free(dirs->data);
+        dirs = g_list_delete_link(dirs, dirs);
+    }
+
+    GVariant *response = g_variant_new("(as)", builder);
+    g_variant_builder_unref(builder);
+
+    return response;
+}
+
+static void handle_method_call(GDBusConnection *connection,
+                        const gchar *caller,
+                        const gchar *object_path,
+                        const gchar *interface_name,
+                        const gchar *method_name,
+                        GVariant    *parameters,
+                        GDBusMethodInvocation *invocation,
+                        gpointer    user_data)
+{
+    reset_timeout();
+    if (g_strcmp0(method_name, "GetProblems") == 0)
+    {
+        GError *error = NULL;
+        GVariant *response;
+        uid_t caller_uid;
+
+
+        caller_uid = get_caller_uid(connection, caller, error);
+
+        if (error)
+        {
+            g_dbus_method_invocation_return_dbus_error(invocation,
+                                      "org.freedesktop.problems.InvalidUser",
+                                      error->message);
+            g_error_free(error);
+            return;
+        }
+        else if (caller_uid == 99)
+        {
+            g_dbus_method_invocation_return_dbus_error(invocation,
+                                      "org.freedesktop.problems.InvalidUser",
+                                      "Unknown error");
+            return;
+        }
+
+        //TODO: change the API to not accept the dumpdir from user, but read 
it from config file?
+
+        const gchar *dump_location;
+        g_variant_get(parameters, "(&s)", &dump_location);
+
+        //if (!g_settings_dump_location)
+        //    g_settings_dump_location = (char*)"/var/spool/abrt";
+
+        response = get_problem_dirs_for_uid(caller_uid, dump_location);
+
+        g_dbus_method_invocation_return_value(invocation, response);
+        //I was told that g_dbus_method frees the response
+        //g_variant_unref(response);
+    }
+
+    else if (g_strcmp0(method_name, "GetAllProblems") == 0)
+    {
+        GVariant *response;
+        GError *error = NULL;
+        uid_t caller_uid;
+
+        const gchar *dump_location;
+        g_variant_get(parameters, "(&s)", &dump_location);
+
+        caller_uid = get_caller_uid(connection, caller, error);
+
+        if (error)
+        {
+            g_dbus_method_invocation_return_dbus_error(invocation,
+                                      "org.freedesktop.problems.InvalidUser",
+                                      error->message);
+            g_error_free(error);
+            return;
+        }
+        else if (caller_uid == 99)
+        {
+            g_dbus_method_invocation_return_dbus_error(invocation,
+                                      "org.freedesktop.problems.InvalidUser",
+                                      "Unknown error");
+            return;
+        }
+
+        /*
+        - so, we have UID,
+        - if it's 0, then we don't have to check anything and just return all 
directories
+        - if uid != 0 then we want to ask for authorization
+        */
+
+        if (caller_uid != 0)
+        {
+            if (polkit_check_authorization_dname(caller, 
"org.freedesktop.problems.getall") == PolkitYes)
+                caller_uid = 0;
+        }
+
+        response = get_problem_dirs_for_uid(caller_uid, dump_location);
+
+        g_dbus_method_invocation_return_value(invocation, response);
+    }
+
+    else if (g_strcmp0(method_name, "ChownProblemDir") == 0)
+    {
+        VERB1 log("ChownProblemDir");
+
+        GError *error = NULL;
+        uid_t caller_uid;
+        const gchar *problem_dir;
+        struct passwd *pwd;
+        int chown_res;
+        gchar *error_msg;
+
+        g_variant_get(parameters, "(&s)", &problem_dir);
+
+        //FIXME: check if it's problem_dir and refuse to operate on it if it's 
not
+        struct dump_dir *dd = dd_opendir(problem_dir, DD_OPEN_READONLY | 
DD_FAIL_QUIETLY_EACCES);
+        if (!dd)
+        {
+            error_msg = g_strdup_printf(_("%s is not a valid problem dir"), 
problem_dir);
+            g_dbus_method_invocation_return_dbus_error(invocation,
+                                      
"org.freedesktop.problems.InvalidProblemDir",
+                                      error_msg);
+            free(error_msg);
+            return;
+        }
+
+        caller_uid = get_caller_uid(connection, caller, error);
+
+        if (error)
+        {
+            g_dbus_method_invocation_return_gerror(invocation, error);
+            g_error_free(error);
+            dd_close(dd);
+            return;
+        }
+
+        if (caller_uid == 99)
+        {
+            error_msg = g_strdup_printf("Could not get unix user for caller 
%s", caller);
+            g_dbus_method_invocation_return_dbus_error(invocation,
+                                      "org.freedesktop.problems.InvalidUser",
+                                      error_msg);
+            free(error_msg);
+            dd_close(dd);
+            return;
+        }
+
+        struct stat statbuf;
+        errno = 0;
+        if (stat(problem_dir, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
+        {
+            if (caller_uid == 0 || uid_in_group(caller_uid, statbuf.st_gid)) 
//caller seems to be in group with access to this dir, so no action needed
+            {
+                //return ok
+                VERB1 log("caller has access to the requested directory %s", 
problem_dir);
+                g_dbus_method_invocation_return_value(invocation, NULL);
+                dd_close(dd);
+                return;
+                //free something?
+            }
+
+        }
+        else
+        {
+            g_dbus_method_invocation_return_dbus_error(invocation,
+                                                      
"org.freedesktop.problems.StatFailure",
+                                                      strerror(errno));
+            dd_close(dd);
+            return;
+        }
+
+        if (polkit_check_authorization_dname(caller, 
"org.freedesktop.problems.getall") != PolkitYes)
+        {
+            VERB1 log("not authorized");
+            g_dbus_method_invocation_return_dbus_error(invocation,
+                                              
"org.freedesktop.problems.AuthFailure",
+                                              "Not Authorized");
+            dd_close(dd);
+            return;
+        }
+
+        pwd = getpwuid(caller_uid);
+        if (pwd)
+        {
+            errno = 0;
+            chown_res = chown(problem_dir, statbuf.st_uid, pwd->pw_gid);
+            dd_init_next_file(dd);
+            char *short_name, *full_name;
+            while (chown_res == 0 && dd_get_next_file(dd, &short_name, 
&full_name))
+            {
+                VERB3 log("chowning %s", full_name);
+                chown_res = chown(full_name, statbuf.st_uid, pwd->pw_gid);
+            }
+
+            if (chown_res != 0)
+                g_dbus_method_invocation_return_dbus_error(invocation,
+                                                  
"org.freedesktop.problems.ChownError",
+                                                  strerror(errno));
+
+            g_dbus_method_invocation_return_value(invocation, NULL);
+            dd_close(dd);
+            return;
+        }
+        VERB3 log("shouldn't get here");
+        dd_close(dd);
+    }
+
+    else if (g_strcmp0(method_name, "GetInfo") == 0)
+    {
+        VERB1 log("GetInfo");
+        GError *error = NULL;
+
+        const gchar *problem_dir;
+        g_variant_get(parameters, "(&s)", &problem_dir);
+
+        GVariantBuilder *builder;
+
+        struct stat statbuf;
+        errno = 0;
+        if (stat(problem_dir, &statbuf) != 0)
+        {
+            g_dbus_method_invocation_return_dbus_error(invocation,
+                                                  
"org.freedesktop.problems.GetInfoError",
+                                                  strerror(errno));
+            return;
+        }
+
+
+        uid_t caller_uid = get_caller_uid(connection, caller, error);
+        if (!uid_in_group(caller_uid, statbuf.st_gid))
+        {
+            if (polkit_check_authorization_dname(caller, 
"org.freedesktop.problems.getall") != PolkitYes)
+            {
+                VERB1 log("not authorized");
+                g_dbus_method_invocation_return_dbus_error(invocation,
+                                                  
"org.freedesktop.problems.AuthFailure",
+                                                  "Not Authorized");
+                return;
+            }
+        }
+
+        struct dump_dir *dd = dd_opendir(problem_dir, DD_OPEN_READONLY | 
DD_FAIL_QUIETLY_EACCES);
+        if (!dd)
+        {
+            char *error_msg = g_strdup_printf(_("%s is not a valid problem 
directory"), problem_dir);
+            g_dbus_method_invocation_return_dbus_error(invocation,
+                                                  
"org.freedesktop.problems.GetInfo",
+                                                  error_msg);
+            free(error_msg);
+        }
+
+        builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
+        g_variant_builder_add (builder, "{ss}", g_strdup(FILENAME_TIME), 
dd_load_text(dd, FILENAME_TIME));
+        g_variant_builder_add (builder, "{ss}", g_strdup(FILENAME_REASON), 
dd_load_text(dd, FILENAME_REASON));
+        char *not_reportable_reason = dd_load_text_ext(dd, 
FILENAME_NOT_REPORTABLE, 0
+                                                       | 
DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+                                                       | DD_FAIL_QUIETLY_ENOENT
+                                                       | 
DD_FAIL_QUIETLY_EACCES);
+        if (not_reportable_reason)
+            g_variant_builder_add (builder, "{ss}", 
g_strdup(FILENAME_NOT_REPORTABLE), dd_load_text_ext(dd, 
FILENAME_NOT_REPORTABLE, 0
+                                                                               
                | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+                                                                               
                | DD_FAIL_QUIETLY_ENOENT
+                                                                               
                | DD_FAIL_QUIETLY_EACCES));
+        /* the source of the problem:
+        * - first we try to load component, as we use it on Fedora
+        */
+        char *source = dd_load_text_ext(dd, FILENAME_COMPONENT, 0
+                    | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+                    | DD_FAIL_QUIETLY_ENOENT
+                    | DD_FAIL_QUIETLY_EACCES
+        );
+        /* if we don't have component, we fallback to executable */
+        if (!source)
+        {
+            source = dd_load_text_ext(dd, FILENAME_EXECUTABLE, 0
+                    | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+                    | DD_FAIL_QUIETLY_ENOENT
+                    | DD_FAIL_QUIETLY_EACCES
+            );
+        }
+
+        g_variant_builder_add (builder, "{ss}", g_strdup("source"), source);
+        char *msg = dd_load_text_ext(dd, FILENAME_REPORTED_TO, 0
+                    | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+                    | DD_FAIL_QUIETLY_ENOENT
+                    | DD_FAIL_QUIETLY_EACCES
+        );
+        if (msg)
+            g_variant_builder_add (builder, "{ss}", 
g_strdup(FILENAME_REPORTED_TO), msg);
+
+        dd_close(dd);
+
+        GVariant *response = g_variant_new("(a{ss})", builder);
+        g_variant_builder_unref(builder);
+
+        g_dbus_method_invocation_return_value(invocation, response);
+    }
+
+    else if (g_strcmp0(method_name, "Quit") == 0)
+    {
+        VERB1 log("Quit");
+
+        g_dbus_method_invocation_return_value(invocation, NULL);
+
+        g_main_loop_quit(loop);
+
+    }
+}
+
+static gboolean on_timeout_cb(gpointer user_data)
+{
+    g_main_loop_quit(loop);
+    return TRUE;
+}
+
+/* for now */
+static const GDBusInterfaceVTable interface_vtable =
+{
+  handle_method_call,
+  NULL,
+  NULL,
+};
+
+static void on_bus_acquired(GDBusConnection *connection,
+                 const gchar     *name,
+                 gpointer         user_data)
+{
+  guint registration_id;
+
+  registration_id = g_dbus_connection_register_object(connection,
+                                                       ABRT_DBUS_OBJECT,
+                                                       
introspection_data->interfaces[0],
+                                                       &interface_vtable,
+                                                       NULL,  /* user_data */
+                                                       NULL,  /* 
user_data_free_func */
+                                                       NULL); /* GError** */
+  g_assert(registration_id > 0);
+
+  reset_timeout();
+}
+
+static void on_name_acquired (GDBusConnection *connection,
+                  const gchar     *name,
+                  gpointer         user_data)
+{
+}
+
+static void on_name_lost (GDBusConnection *connection,
+                  const gchar *name,
+                      gpointer user_data)
+{
+    g_print(_("The name '%s' has been lost, please check if other "
+              "service owning the name is not running.\n"), name);
+    exit(1);
+}
+
+int main (int argc, char *argv[])
+{
+    /* I18n */
+    setlocale(LC_ALL, "");
+#if ENABLE_NLS
+    bindtextdomain(PACKAGE, LOCALEDIR);
+    textdomain(PACKAGE);
+#endif
+    guint owner_id;
+
+    abrt_init(argv);
+
+    const char *program_usage_string = _(
+        "& [options]"
+    );
+    enum {
+        OPT_v = 1 << 0,
+        OPT_t = 1 << 1,
+    };
+    /* Keep enum above and order of options below in sync! */
+    struct options program_options[] = {
+        OPT__VERBOSE(&g_verbose),
+        OPT_INTEGER('t', NULL, &s_timeout, _("Exit after NUM seconds of 
inactivity")),
+        OPT_END()
+    };
+    unsigned opts = parse_opts(argc, argv, program_options, 
program_usage_string);
+
+    export_abrt_envvars(0);
+
+    /* When dbus daemon starts us, it doesn't set PATH
+     * (I saw it set only DBUS_STARTER_ADDRESS and DBUS_STARTER_BUS_TYPE).
+     * In this case, set something sane:
+     */
+    const char *env_path = getenv("PATH");
+    if (!env_path || !env_path[0])
+        putenv((char*)"PATH=/usr/sbin:/usr/bin:/sbin:/bin");
+
+    msg_prefix = "abrt-dbus"; /* for log(), error_msg() and such */
+
+    if (!(opts & OPT_t))
+        s_timeout = 120; //if the timeout is not set we default to 120sec
+
+    if (getuid() != 0)
+        error_msg_and_die(_("This program must be run as root."));
+
+    g_type_init();
+
+
+    /* We are lazy here - we don't want to manually provide
+    * the introspection data structures - so we just build
+    * them from XML.
+    */
+    introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
+    g_assert(introspection_data != NULL);
+
+    owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
+                             ABRT_DBUS_NAME,
+                             G_BUS_NAME_OWNER_FLAGS_NONE,
+                             on_bus_acquired,
+                             on_name_acquired,
+                             on_name_lost,
+                             NULL,
+                             NULL);
+
+    loop = g_main_loop_new(NULL, FALSE);
+    g_main_loop_run(loop);
+
+    VERB1 log("Cleaning up");
+
+    g_bus_unown_name(owner_id);
+
+    g_dbus_node_info_unref(introspection_data);
+
+    return 0;
+}
+
diff --git a/src/dbus/abrt-polkit.c b/src/dbus/abrt-polkit.c
new file mode 100644
index 0000000..d90baf4
--- /dev/null
+++ b/src/dbus/abrt-polkit.c
@@ -0,0 +1,102 @@
+/*
+  Copyright (C) 2012  ABRT team
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <polkit/polkit.h>
+#include <glib-object.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "libabrt.h"
+#include "abrt-polkit.h"
+
+/*number of seconds: timeout for the authorization*/
+#define POLKIT_TIMEOUT 20
+
+static gboolean do_cancel(GCancellable* cancellable)
+{
+    log("Timer has expired; cancelling authorization check\n");
+    g_cancellable_cancel(cancellable);
+    return FALSE;
+}
+
+
+static PolkitResult do_check(PolkitSubject *subject, const char *action_id)
+{
+    PolkitAuthority *authority;
+    PolkitAuthorizationResult *result;
+    GError *error = NULL;
+    GCancellable * cancellable;
+
+    cancellable = g_cancellable_new();
+
+    /* we ignore the error for now .. */
+    authority = polkit_authority_get_sync(cancellable, NULL);
+
+    guint cancel_timeout = g_timeout_add(POLKIT_TIMEOUT * 1000,
+                   (GSourceFunc) do_cancel,
+                   cancellable);
+
+    result = polkit_authority_check_authorization_sync(authority,
+                subject,
+                action_id,
+                NULL,
+                POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+                cancellable,
+                &error);
+    g_object_unref(authority);
+    g_source_remove(cancel_timeout);
+    if (error)
+    {
+        g_error_free(error);
+        return PolkitUnknown;
+    }
+
+    if (result)
+    {
+        if (polkit_authorization_result_get_is_challenge(result))
+        {
+            /* Can't happen (happens only with
+             * POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE flag) */
+            g_object_unref(result);
+            return PolkitChallenge;
+        }
+        if (polkit_authorization_result_get_is_authorized(result))
+        {
+            g_object_unref(result);
+            return PolkitYes;
+        }
+        g_object_unref(result);
+        return PolkitNo;
+    }
+
+    return PolkitUnknown;
+}
+
+PolkitResult polkit_check_authorization_dname(const char *dbus_name, const 
char *action_id)
+{
+    g_type_init();
+    PolkitSubject *subject = polkit_system_bus_name_new(dbus_name);
+    return do_check(subject, action_id);
+}
+
+PolkitResult polkit_check_authorization_pid(pid_t pid, const char *action_id)
+{
+    g_type_init();
+    PolkitSubject *subject = polkit_unix_process_new(pid);
+    return do_check(subject, action_id);
+}
diff --git a/src/dbus/abrt-polkit.h b/src/dbus/abrt-polkit.h
new file mode 100644
index 0000000..0f6eb1e
--- /dev/null
+++ b/src/dbus/abrt-polkit.h
@@ -0,0 +1,39 @@
+/*
+  Copyright (C) 2012  ABRT team
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef ABRT_POLKIT_H
+#define ABRT_POLKIT_H
+
+#include <sys/types.h>
+#include <unistd.h>
+
+typedef enum {
+/* Authorization status is unknown */
+    PolkitUnknown = 0x0,
+    /* Subject is authorized for the action */
+    PolkitYes = 0x01,
+    /* Subject is not authorized for the action */
+    PolkitNo = 0x02,
+    /* Challenge is needed for this action, only when flag is
+     * POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE */
+    PolkitChallenge = 0x03
+} PolkitResult;
+
+PolkitResult polkit_check_authorization_dname(const char *dbus_name, const 
char *action_id);
+PolkitResult polkit_check_authorization_pid(pid_t pid, const char *action_id);
+
+#endif
diff --git a/src/dbus/abrt_polkit.policy b/src/dbus/abrt_polkit.policy
new file mode 100644
index 0000000..7e7af94
--- /dev/null
+++ b/src/dbus/abrt_polkit.policy
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd";>
+
+<!--
+PolicyKit policy definitions for ABRT
+
+Copyright (c) 2012 ABRT Team <[email protected]>
+
+-->
+
+<policyconfig>
+  <vendor>The ABRT Team</vendor>
+  <vendor_url>https://fedorahosted.org/abrt/</vendor_url>
+
+  <!-- install-debuginfos: default yes, administrator can change this -->
+  <action id="org.freedesktop.problems.getall">
+    <description>Get problems from all users</description>
+    <message>Reading others problems requires authentication</message>
+    <defaults>
+      <allow_any>no</allow_any>
+      <allow_active>auth_admin_keep</allow_active>
+      <allow_inactive>no</allow_inactive>
+    </defaults>
+  </action>
+
+</policyconfig>
diff --git a/src/dbus/dbus-abrt.conf b/src/dbus/dbus-abrt.conf
new file mode 100644
index 0000000..ba09762
--- /dev/null
+++ b/src/dbus/dbus-abrt.conf
@@ -0,0 +1,25 @@
+<!-- This configuration file specifies the required security policies
+     for abrt core daemon to work. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 
1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd";>
+<busconfig>
+
+  <!-- ../system.conf have denied everything, so we just punch some holes -->
+
+  <policy user="root">
+    <allow own="org.freedesktop.problems"/>
+    <allow send_destination="org.freedesktop.problems"/>
+    <allow send_interface="org.freedesktop.problems"/>
+  </policy>
+
+  <policy at_console="true">
+    <allow send_destination="org.freedesktop.org"/>
+  </policy>
+
+  <!-- Allow anyone to invoke methods on abrt server -->
+  <policy context="default">
+    <allow send_destination="org.freedesktop.problems"/>
+  </policy>
+
+</busconfig>
diff --git a/src/dbus/org.freedesktop.problems.service 
b/src/dbus/org.freedesktop.problems.service
new file mode 100644
index 0000000..e8e3bf1
--- /dev/null
+++ b/src/dbus/org.freedesktop.problems.service
@@ -0,0 +1,7 @@
+[D-BUS Service]
+Name=org.freedesktop.problems
+# For testing, you may use -t5 to use small timeout of 5 seconds.
+# This will make "abrtd exited while clients existed but were idle"
+# situations easier to trigger
+Exec=/usr/sbin/abrt-dbus -t133
+User=root
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index c3317d7..f98e2d5 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -2,4 +2,5 @@ libabrt_includedir = \
     $(includedir)/abrt
 
 libabrt_include_HEADERS = \
-    libabrt.h
+    libabrt.h \
+    abrt-dbus.h
diff --git a/src/include/abrt-dbus.h b/src/include/abrt-dbus.h
new file mode 100644
index 0000000..898dd94
--- /dev/null
+++ b/src/include/abrt-dbus.h
@@ -0,0 +1,8 @@
+#ifndef ABRTDBUS_H_
+#define ABRTDBUS_H_
+
+#define ABRT_DBUS_NAME      "org.freedesktop.problems"
+#define ABRT_DBUS_OBJECT     "/org/freedesktop/problems"
+#define ABRT_DBUS_IFACE    "org.freedesktop.problems"
+
+#endif /* ABRTDBUS_H_ */
-- 
1.7.7.6

Reply via email to