--- .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 | 584 +++++++++++++++++++++++++++++ src/dbus/abrt-polkit.c | 104 +++++ 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, 858 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 jmoskovc@redhat.com 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..465b77e --- /dev/null +++ b/src/dbus/abrt-dbus.c @@ -0,0 +1,584 @@ +#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); +} + +static uid_t get_caller_uid(GDBusConnection *connection, GDBusMethodInvocation *invocation, const char *caller) +{ + GError *error = NULL; + 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) + { + /* we failed to get the uid, so return (uid_t) -1 to indicate the error + */ + if (error) + { + g_dbus_method_invocation_return_dbus_error(invocation, + "org.freedesktop.problems.InvalidUser", + error->message); + g_error_free(error); + } + else + { + g_dbus_method_invocation_return_dbus_error(invocation, + "org.freedesktop.problems.InvalidUser", + "Unknown error"); + } + return (uid_t) -1; + } + + g_variant_get(result, "(u)", &caller_uid); + g_variant_unref(result); + + VERB2 log("Caller uid: %i", caller_uid); + return caller_uid; +} + +static bool uid_in_group(uid_t uid, gid_t gid) +{ + char **tmp; + struct passwd *pwd = getpwuid(uid); + + if (!pwd) + return FALSE; + + if (pwd->pw_gid == gid) + return TRUE; + + struct group *grp = getgrgid(gid); + if (!(grp && grp->gr_mem)) + return FALSE; + + 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("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); +} + +static 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(); + uid_t caller_uid; + GVariant *response; + + if (g_strcmp0(method_name, "GetProblems") == 0) + { + + caller_uid = get_caller_uid(connection, invocation, caller); + + if (caller_uid == (uid_t) -1) + 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) + { + + const gchar *dump_location; + g_variant_get(parameters, "(&s)", &dump_location); + + caller_uid = get_caller_uid(connection, invocation, caller); + + if (caller_uid == (uid_t) -1) + 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); + return; + } + + else if (g_strcmp0(method_name, "ChownProblemDir") == 0) + { + VERB1 log("ChownProblemDir"); + + 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, invocation, caller); + + if (caller_uid == (uid_t) -1) + 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"); + + 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; + } + + + caller_uid = get_caller_uid(connection, invocation, caller); + + if (caller_uid == (uid_t) -1) + return; + + 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..29973e5 --- /dev/null +++ b/src/dbus/abrt-polkit.c @@ -0,0 +1,104 @@ +/* + 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 *auth_result; + PolkitResult result = PolkitNo; + 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); + + auth_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 (!auth_result) + return PolkitUnknown; + + if (polkit_authorization_result_get_is_challenge(auth_result)) + { + /* Can't happen (happens only with + * POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE flag) */ + result = PolkitChallenge; + goto out; + } + + if (polkit_authorization_result_get_is_authorized(auth_result)) + { + result = PolkitYes; + goto out; + } + +out: + g_object_unref(auth_result); + return result; +} + +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 <crash-catcher@fedorahosted.com> + +--> + +<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_ */
--- src/gui-gtk/Makefile.am | 6 +- src/gui-gtk/main.c | 206 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 151 insertions(+), 61 deletions(-)
diff --git a/src/gui-gtk/Makefile.am b/src/gui-gtk/Makefile.am index 734899e..2ce69c5 100644 --- a/src/gui-gtk/Makefile.am +++ b/src/gui-gtk/Makefile.am @@ -10,6 +10,7 @@ abrt_gui_CFLAGS = \ $(GTK_CFLAGS) \ $(LIBREPORT_GTK_CFLAGS) \ -D_GNU_SOURCE \ + $(GIO_CFLAGS) \ -Wall -Wwrite-strings -Werror # -I/usr/include/glib-2.0 # -I/usr/lib/glib-2.0/include @@ -18,9 +19,10 @@ abrt_gui_CFLAGS = \ abrt_gui_LDADD = \ -lglib-2.0 \ -lgthread-2.0 \ - $(GTK_LIBS) \ + $(GIO_LIBS) \ $(LIBREPORT_GTK_LIBS) \ - ../lib/libabrt.la + ../lib/libabrt.la \ + $(GTK_LIBS) # $(LIBNOTIFY_LIBS)
#test_report_SOURCES = \ diff --git a/src/gui-gtk/main.c b/src/gui-gtk/main.c index f34ff3f..777d9df 100644 --- a/src/gui-gtk/main.c +++ b/src/gui-gtk/main.c @@ -19,11 +19,13 @@ #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> #include <sys/inotify.h> +#include <gio/gio.h> //dbus #if HAVE_LOCALE_H # include <locale.h> #endif #include <internal_libreport_gtk.h> #include "libabrt.h" +#include "abrt-dbus.h"
#if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 22 # define GDK_KEY_Delete GDK_Delete @@ -31,6 +33,7 @@ #endif
static void scan_dirs_and_add_to_dirlist(void); +static void rescan_and_refresh(void);
static const char help_uri[] = "http://docs.fedoraproject.org/en-US/" @@ -59,6 +62,8 @@ enum NUM_COLUMNS };
+gint g_authorize; /* wheter to try to authorize when getting list of problems */ + //FIXME: maybe we can use strrchr and make this faster... static char *get_last_line(const char* msg) { @@ -84,22 +89,60 @@ static char *get_last_line(const char* msg) return xstrndup(start, end - start); }
-static void add_directory_to_dirlist(const char *dirname) +static problem_data_t* get_problem_data_dbus(const char *problem_dir_path, GError *error) +{ + problem_data_t *pd; + char *key, *val; + + GDBusProxy *proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + ABRT_DBUS_NAME, + ABRT_DBUS_OBJECT, + ABRT_DBUS_IFACE, + NULL, + &error); + + GVariant *result = g_dbus_proxy_call_sync(proxy, + "GetInfo", + g_variant_new("(s)", problem_dir_path), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + pd = new_problem_data(); + + GVariantIter *iter; + g_variant_get(result, "(a{ss})", &iter); + while (g_variant_iter_loop(iter, "{ss}", &key, &val)) + { + add_to_problem_data(pd, key, val); + } + return pd; +} + +static void add_directory_to_dirlist(gpointer dir, gpointer data) { + const char *dirname = (const char *)dir; /* 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(dirname, DD_OPEN_READONLY | DD_FAIL_QUIETLY_EACCES); logmode = sv_logmode; + /* + struct dump_dir *dd = dd_opendir(dirname, DD_OPEN_READONLY | DD_FAIL_QUIETLY_EACCES); + if (!dd) return; + */
+ problem_data_t *pd = get_problem_data_dbus(dir, NULL); char time_buf[sizeof("YYYY-MM-DD hh:mm:ss")]; time_buf[0] = '\0'; - char *time_str = dd_load_text(dd, FILENAME_TIME); + const char *time_str = get_problem_item_content_or_NULL(pd, FILENAME_TIME); time_t t = 0; if (time_str && time_str[0]) { @@ -108,40 +151,18 @@ static void add_directory_to_dirlist(const char *dirname) size_t time_len = strftime(time_buf, sizeof(time_buf)-1, "%Y-%m-%d %H:%M", ptm); time_buf[time_len] = '\0'; } - free(time_str); -
- 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); - char *reason = NULL; - if (!not_reportable_reason) - reason = dd_load_text(dd, FILENAME_REASON); + const char *not_reportable_reason = get_problem_item_content_or_NULL(pd, FILENAME_NOT_REPORTABLE); + const char *reason = get_problem_item_content_or_NULL(pd, FILENAME_REASON); + //if (!not_reportable_reason) + // reason = get_problem_item_content_or_NULL(pd, FILENAME_REASON);
/* 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 - ); - } + const char *source = get_problem_item_content_or_NULL(pd, "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 - ); + const char *msg = get_problem_item_content_or_NULL(pd, FILENAME_REPORTED_TO);
GtkListStore *list_store; @@ -166,16 +187,55 @@ static void add_directory_to_dirlist(const char *dirname) COLUMN_DUMP_DIR, dirname, COLUMN_REPORTED_TO, msg ? subm_status : NULL, -1); - /* this is safe, subm_status is either null or malloced string from get_last_line */ - free(not_reportable_reason); - free(subm_status); - free(msg); - free(reason);
- dd_close(dd); + free_problem_data(pd); + VERB1 log("added: %s", dirname); }
+GList *get_problems_over_dbus(const char *dump_location, GError *error) +{ + GDBusProxy * proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + ABRT_DBUS_NAME, + ABRT_DBUS_OBJECT, + ABRT_DBUS_IFACE, + NULL, + &error); + +/* + GDBusProxy * proxy = g_dbus_proxy_new_sync(connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.freedesktop.problems", + "/org/freedesktop/problems", + "org.freedesktop.problems", + NULL, + &error); +*/ + + GVariant *result = g_dbus_proxy_call_sync(proxy, + g_authorize ? "GetAllProblems" : "GetProblems", + g_variant_new("(s)", dump_location), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + GList *list = NULL; + GVariantIter *iter; + gchar *str; + g_variant_get(result, "(as)", &iter); + while (g_variant_iter_loop(iter, "s", &str)) + { + VERB1 log("adding: %s\n", str); + list = g_list_prepend(list, xstrdup(str)); + } + g_variant_iter_free(iter); + + return list; +} + static void rescan_dirs_and_add_to_dirlist(void) { gtk_list_store_clear(s_dumps_list_store); @@ -344,6 +404,35 @@ static gboolean on_focus_cb( return false; /* propagate the event further */ }
+static int chown_dir_over_dbus(const char *problem_dir_path) +{ + GError *error; + GDBusProxy * proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + ABRT_DBUS_NAME, + ABRT_DBUS_OBJECT, + ABRT_DBUS_IFACE, + NULL, + &error); + + g_dbus_proxy_call_sync(proxy, + "ChownProblemDir", + g_variant_new("(s)", problem_dir_path), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (error) + { + //TODO show a warning dialog here or on the higher level? + error_msg(_("Can't chown '%s': %s"),problem_dir_path, error->message); + return 1; + } + return 0; +} + static void on_row_activated_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data) { GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview); @@ -358,8 +447,13 @@ static void on_row_activated_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTre
const char *dirname = g_value_get_string(&d_dir);
- report_problem_in_dir(dirname, + if (chown_dir_over_dbus(dirname) == 0) + { + report_problem_in_dir(dirname, LIBREPORT_ANALYZE | LIBREPORT_NOWAIT | LIBREPORT_GETPID); + } + //else + // TODO: show a warning dialog } } } @@ -392,6 +486,12 @@ static void on_column_change_cb(GtkTreeSortable *sortable, gpointer user_data) free(value); }
+static void on_show_all_cb(GtkToggleButton *togglebutton, gpointer data) +{ + g_authorize = gtk_toggle_button_get_active(togglebutton); + rescan_and_refresh(); +} + static void load_sort_setting(GtkTreeSortable *sortable) { const char *name, *value; @@ -754,10 +854,14 @@ static GtkWidget *create_main_window(void) gtk_misc_set_alignment(GTK_MISC(not_subm_lbl), 0, 0); gtk_label_set_markup(GTK_LABEL(not_subm_lbl), _("<b>Not submitted reports</b>"));
+ GtkWidget *show_all_btn = gtk_check_button_new_with_label(_("Show all problems")); + g_signal_connect(show_all_btn, "toggled", G_CALLBACK(on_show_all_cb), NULL); + /* add label for not submitted tree view */ gtk_box_pack_start(GTK_BOX(not_subm_vbox), not_subm_lbl, false, false, 0); gtk_box_pack_start(GTK_BOX(not_subm_vbox), new_problems_scroll_win, true, true, 0); gtk_box_pack_start(GTK_BOX(main_vbox), not_subm_vbox, true, true, 0); + gtk_box_pack_start(GTK_BOX(main_vbox), show_all_btn, false, false, 0);
/* Two tree views */ s_treeview = gtk_tree_view_new(); @@ -988,27 +1092,11 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin
static void scan_directory_and_add_to_dirlist(const char *path) { - 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; - } - - 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)) - add_directory_to_dirlist(full_name); - free(full_name); - } - closedir(dp); + GList *problem_dirs = get_problems_over_dbus(path, NULL); + if (problem_dirs) + g_list_foreach(problem_dirs, (GFunc)add_directory_to_dirlist, NULL); + else + error_msg_and_die(_("Can't get problem list from abrt-dbus"));
if (inotify_fd >= 0 && inotify_add_watch(inotify_fd, path, 0 // | IN_ATTRIB // Metadata changed
Jiri Moskovcak jmoskovc@redhat.com writes:
src/gui-gtk/Makefile.am | 6 +- src/gui-gtk/main.c | 206 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 151 insertions(+), 61 deletions(-)
diff --git a/src/gui-gtk/main.c b/src/gui-gtk/main.c index f34ff3f..777d9df 100644 --- a/src/gui-gtk/main.c +++ b/src/gui-gtk/main.c @@ -19,11 +19,13 @@ #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> #include <sys/inotify.h> +#include <gio/gio.h> //dbus #if HAVE_LOCALE_H # include <locale.h> #endif #include <internal_libreport_gtk.h> #include "libabrt.h" +#include "abrt-dbus.h"
#if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 22 # define GDK_KEY_Delete GDK_Delete @@ -31,6 +33,7 @@ #endif
static void scan_dirs_and_add_to_dirlist(void); +static void rescan_and_refresh(void);
static const char help_uri[] = "http://docs.fedoraproject.org/en-US/" @@ -59,6 +62,8 @@ enum NUM_COLUMNS };
+gint g_authorize; /* wheter to try to authorize when getting list of problems */
also static
//FIXME: maybe we can use strrchr and make this faster... static char *get_last_line(const char* msg) { @@ -84,22 +89,60 @@ static char *get_last_line(const char* msg) return xstrndup(start, end - start); }
-static void add_directory_to_dirlist(const char *dirname) +static problem_data_t* get_problem_data_dbus(const char *problem_dir_path, GError *error) +{
- problem_data_t *pd;
- char *key, *val;
- GDBusProxy *proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
ABRT_DBUS_NAME,
ABRT_DBUS_OBJECT,
ABRT_DBUS_IFACE,
NULL,
&error);
- GVariant *result = g_dbus_proxy_call_sync(proxy,
"GetInfo",
g_variant_new("(s)", problem_dir_path),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
- pd = new_problem_data();
- GVariantIter *iter;
- g_variant_get(result, "(a{ss})", &iter);
- while (g_variant_iter_loop(iter, "{ss}", &key, &val))
- {
add_to_problem_data(pd, key, val);
- }
- return pd;
+}
+static void add_directory_to_dirlist(gpointer dir, gpointer data)
why gpointer dir? use const char *dir
{
- const char *dirname = (const char *)dir; /* Silently ignore *any* errors, not only EACCES.
*/ int sv_logmode = logmode; logmode = 0;
- We saw "lock file is locked by process PID" error
- when we raced with wizard.
- struct dump_dir *dd = dd_opendir(dirname, DD_OPEN_READONLY | DD_FAIL_QUIETLY_EACCES); logmode = sv_logmode;
- /*
- struct dump_dir *dd = dd_opendir(dirname, DD_OPEN_READONLY | DD_FAIL_QUIETLY_EACCES);
- if (!dd) return;
- */
do not coment it out; remove it
- problem_data_t *pd = get_problem_data_dbus(dir, NULL); char time_buf[sizeof("YYYY-MM-DD hh:mm:ss")]; time_buf[0] = '\0';
- char *time_str = dd_load_text(dd, FILENAME_TIME);
- const char *time_str = get_problem_item_content_or_NULL(pd, FILENAME_TIME); time_t t = 0; if (time_str && time_str[0]) {
@@ -108,40 +151,18 @@ static void add_directory_to_dirlist(const char *dirname) size_t time_len = strftime(time_buf, sizeof(time_buf)-1, "%Y-%m-%d %H:%M", ptm); time_buf[time_len] = '\0'; }
free(time_str);
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);
char *reason = NULL;
if (!not_reportable_reason)
reason = dd_load_text(dd, FILENAME_REASON);
- const char *not_reportable_reason = get_problem_item_content_or_NULL(pd, FILENAME_NOT_REPORTABLE);
- const char *reason = get_problem_item_content_or_NULL(pd, FILENAME_REASON);
- //if (!not_reportable_reason)
- // reason = get_problem_item_content_or_NULL(pd, FILENAME_REASON);
remove comments
/* 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
);
- }
- const char *source = get_problem_item_content_or_NULL(pd, "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
- );
const char *msg = get_problem_item_content_or_NULL(pd, FILENAME_REPORTED_TO);
GtkListStore *list_store;
@@ -166,16 +187,55 @@ static void add_directory_to_dirlist(const char *dirname) COLUMN_DUMP_DIR, dirname, COLUMN_REPORTED_TO, msg ? subm_status : NULL, -1);
/* this is safe, subm_status is either null or malloced string from get_last_line */
free(not_reportable_reason);
free(subm_status);
free(msg);
free(reason);
dd_close(dd);
- free_problem_data(pd);
- VERB1 log("added: %s", dirname);
}
+GList *get_problems_over_dbus(const char *dump_location, GError *error) +{
- GDBusProxy * proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
ABRT_DBUS_NAME,
ABRT_DBUS_OBJECT,
ABRT_DBUS_IFACE,
NULL,
&error);
+/*
- GDBusProxy * proxy = g_dbus_proxy_new_sync(connection,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.freedesktop.problems",
"/org/freedesktop/problems",
"org.freedesktop.problems",
NULL,
&error);
+*/
remove comment
- GVariant *result = g_dbus_proxy_call_sync(proxy,
g_authorize ? "GetAllProblems" : "GetProblems",
g_variant_new("(s)", dump_location),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
- GList *list = NULL;
- GVariantIter *iter;
- gchar *str;
- g_variant_get(result, "(as)", &iter);
- while (g_variant_iter_loop(iter, "s", &str))
- {
VERB1 log("adding: %s\n", str);
list = g_list_prepend(list, xstrdup(str));
- }
- g_variant_iter_free(iter);
- return list;
+}
static void rescan_dirs_and_add_to_dirlist(void) { gtk_list_store_clear(s_dumps_list_store); @@ -344,6 +404,35 @@ static gboolean on_focus_cb( return false; /* propagate the event further */ }
+static int chown_dir_over_dbus(const char *problem_dir_path) +{
- GError *error;
- GDBusProxy * proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
ABRT_DBUS_NAME,
ABRT_DBUS_OBJECT,
ABRT_DBUS_IFACE,
NULL,
&error);
g_dbus_proxy_call_sync(proxy,
"ChownProblemDir",
g_variant_new("(s)", problem_dir_path),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (error)
{
//TODO show a warning dialog here or on the higher level?
error_msg(_("Can't chown '%s': %s"),problem_dir_path, error->message);
return 1;
}
return 0;
+}
total off indentation and without freeing *error*
static void on_row_activated_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data) { GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview); @@ -358,8 +447,13 @@ static void on_row_activated_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTre
const char *dirname = g_value_get_string(&d_dir);
report_problem_in_dir(dirname,
if (chown_dir_over_dbus(dirname) == 0)
{
report_problem_in_dir(dirname, LIBREPORT_ANALYZE | LIBREPORT_NOWAIT | LIBREPORT_GETPID);
}
//else
}// TODO: show a warning dialog }
} @@ -392,6 +486,12 @@ static void on_column_change_cb(GtkTreeSortable *sortable, gpointer user_data) free(value); }
+static void on_show_all_cb(GtkToggleButton *togglebutton, gpointer data) +{
- g_authorize = gtk_toggle_button_get_active(togglebutton);
- rescan_and_refresh();
+}
static void load_sort_setting(GtkTreeSortable *sortable) { const char *name, *value; @@ -754,10 +854,14 @@ static GtkWidget *create_main_window(void) gtk_misc_set_alignment(GTK_MISC(not_subm_lbl), 0, 0); gtk_label_set_markup(GTK_LABEL(not_subm_lbl), _("<b>Not submitted reports</b>"));
GtkWidget *show_all_btn = gtk_check_button_new_with_label(_("Show all problems"));
g_signal_connect(show_all_btn, "toggled", G_CALLBACK(on_show_all_cb), NULL);
/* add label for not submitted tree view */ gtk_box_pack_start(GTK_BOX(not_subm_vbox), not_subm_lbl, false, false, 0); gtk_box_pack_start(GTK_BOX(not_subm_vbox), new_problems_scroll_win, true, true, 0); gtk_box_pack_start(GTK_BOX(main_vbox), not_subm_vbox, true, true, 0);
gtk_box_pack_start(GTK_BOX(main_vbox), show_all_btn, false, false, 0);
/* Two tree views */ s_treeview = gtk_tree_view_new();
@@ -988,27 +1092,11 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin
static void scan_directory_and_add_to_dirlist(const char *path) {
- 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;
- }
- 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))
add_directory_to_dirlist(full_name);
free(full_name);
- }
- closedir(dp);
GList *problem_dirs = get_problems_over_dbus(path, NULL);
if (problem_dirs)
g_list_foreach(problem_dirs, (GFunc)add_directory_to_dirlist, NULL);
else
error_msg_and_die(_("Can't get problem list from abrt-dbus"));
if (inotify_fd >= 0 && inotify_add_watch(inotify_fd, path, 0 // | IN_ATTRIB // Metadata changed
Jiri Moskovcak jmoskovc@redhat.com writes:
+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();
- uid_t caller_uid;
- GVariant *response;
- if (g_strcmp0(method_name, "GetProblems") == 0)
- {
^ pointless new line
caller_uid = get_caller_uid(connection, invocation, caller);
if (caller_uid == (uid_t) -1)
return;
exctract from all parts of if () caller_uid and check before if's
- }
^ pointless new line before every *else if*
- else if (g_strcmp0(method_name, "GetAllProblems") == 0)
- {
dito
- }
- else if (g_strcmp0(method_name, "ChownProblemDir") == 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
remove comment
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?
dito comment
}
}
else
{
g_dbus_method_invocation_return_dbus_error(invocation,
"org.freedesktop.problems.StatFailure",
strerror(errno));
dd_close(dd);
return;
}
pwd = getpwuid(caller_uid);
if (pwd)
{
errno = 0;
chown_res = chown(problem_dir, statbuf.st_uid, pwd->pw_gid);
you don't have to set errno to 0, because if chown on success return 0. On error -1 errno is set.
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)
according to man-pages, you should have to check -1
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");
const gchar *problem_dir;
g_variant_get(parameters, "(&s)", &problem_dir);
GVariantBuilder *builder;
struct stat statbuf;
errno = 0;
do not reset errno unless it's needed
On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
if (stat(problem_dir, &statbuf) != 0)
{
g_dbus_method_invocation_return_dbus_error(invocation,
"org.freedesktop.problems.GetInfoError",
strerror(errno));
return;
}
caller_uid = get_caller_uid(connection, invocation, caller);
if (caller_uid == (uid_t) -1)
return;
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");
^^^ not translatable some others are not translatable also
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);
}
here is a bug, when dd is NULL then you print msg and continue to dd_load_text(dd... to have to exit here.
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);
according to me, you are leaking everywhere here. g_variant_builde_unref only count donw reference counter and you should take care of all returned vaules from load_text and g_strdup (and of course you should have to use xstrdup or check g_strdup to NULL)
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);
- }
+}
+/* for now */ +static const GDBusInterfaceVTable interface_vtable = +{
- handle_method_call,
- NULL,
- NULL,
+};
this looks like a function. I don't have any strong opinion here, but more readable solution is
static const foo = { .x = bar; };
what is problem here is big or little endians. C doen't guarantee order of list fields. you have to use
static const GDBusInterfaceVTable interface_vtable = { .GDBusInterfaceMethodCallFunc = handle_method_call, .GDBusInterfaceGetPropertyFunc = NULL, .GDBusInterfaceSetPropertyFunc = NULL, };
+static void on_name_acquired (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
+{ +}
e? couldn't be set to NULL at g_bus_own_name call?
+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);
daemon should not 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
s_timeout is not used; it's write only
+static PolkitResult do_check(PolkitSubject *subject, const char *action_id) +{
... ... ...
- if (polkit_authorization_result_get_is_challenge(auth_result))
- {
/* Can't happen (happens only with
* POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE flag) */
result = PolkitChallenge;
goto out;
- }
- if (polkit_authorization_result_get_is_authorized(auth_result))
- {
result = PolkitYes;
goto out;
pointless goto; you will reach the out after jump off the *if*
- }
+out:
- g_object_unref(auth_result);
- return result;
+}
comment please, because I haven't run it yet
On 03/22/2012 05:24 PM, Nikola Pajkovsky wrote:
Jiri Moskovcakjmoskovc@redhat.com writes:
+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();
- uid_t caller_uid;
- GVariant *response;
- if (g_strcmp0(method_name, "GetProblems") == 0)
- {
^ pointless new line
- fixed
caller_uid = get_caller_uid(connection, invocation, caller);
if (caller_uid == (uid_t) -1)
return;
exctract from all parts of if () caller_uid and check before if's
- moved to the top
- }
^ pointless new line before every *else if*
- it's there for a reason because those else if are quite separate blocks, so I want to make it more obvious
- else if (g_strcmp0(method_name, "GetAllProblems") == 0)
- {
dito
- }
- else if (g_strcmp0(method_name, "ChownProblemDir") == 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
remove comment
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?
dito comment
- fixed
}
}
else
{
g_dbus_method_invocation_return_dbus_error(invocation,
"org.freedesktop.problems.StatFailure",
strerror(errno));
dd_close(dd);
return;
}
pwd = getpwuid(caller_uid);
if (pwd)
{
errno = 0;
chown_res = chown(problem_dir, statbuf.st_uid, pwd->pw_gid);
you don't have to set errno to 0, because if chown on success return 0. On error -1 errno is set.
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)
according to man-pages, you should have to check -1
- according to man pages 0 means success, so anything != 0 isn't OK
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");
const gchar *problem_dir;
g_variant_get(parameters, "(&s)",&problem_dir);
GVariantBuilder *builder;
struct stat statbuf;
errno = 0;
do not reset errno unless it's needed
On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
- I prefer to set it to 0 before using it, it feels "safer"
if (stat(problem_dir,&statbuf) != 0)
{
g_dbus_method_invocation_return_dbus_error(invocation,
"org.freedesktop.problems.GetInfoError",
strerror(errno));
return;
}
caller_uid = get_caller_uid(connection, invocation, caller);
if (caller_uid == (uid_t) -1)
return;
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");
^^^ not translatable
some others are not translatable also
- fixed
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);
}
here is a bug, when dd is NULL then you print msg and continue to dd_load_text(dd... to have to exit here.
- fixed
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);
according to me, you are leaking everywhere here. g_variant_builde_unref only count donw reference counter and you should take care of all returned vaules from load_text and g_strdup (and of course you should have to use xstrdup or check g_strdup to NULL)
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);
- }
+}
+/* for now */ +static const GDBusInterfaceVTable interface_vtable = +{
- handle_method_call,
- NULL,
- NULL,
+};
this looks like a function. I don't have any strong opinion here, but more readable solution is
static const foo = { .x = bar; };
what is problem here is big or little endians. C doen't guarantee order of list fields. you have to use
static const GDBusInterfaceVTable interface_vtable = { .GDBusInterfaceMethodCallFunc = handle_method_call, .GDBusInterfaceGetPropertyFunc = NULL, .GDBusInterfaceSetPropertyFunc = NULL, };
- ok, changed to:
static const GDBusInterfaceVTable interface_vtable = { .method_call = handle_method_call, .get_property = NULL, .set_property = NULL, };
+static void on_name_acquired (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
+{ +}
e? couldn't be set to NULL at g_bus_own_name call?
- ok
+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);
daemon should not exit(1)
- why not? it failed to initialize, so we should inform user about it...
+}
+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
s_timeout is not used; it's write only
- no, it's not: 55: g_timeout = g_timeout_add_seconds(s_timeout, on_timeout_cb, NULL);
+static PolkitResult do_check(PolkitSubject *subject, const char *action_id) +{
... ... ...
- if (polkit_authorization_result_get_is_challenge(auth_result))
- {
/* Can't happen (happens only with
* POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE flag) */
result = PolkitChallenge;
goto out;
- }
- if (polkit_authorization_result_get_is_authorized(auth_result))
- {
result = PolkitYes;
goto out;
pointless goto; you will reach the out after jump off the *if*
- well, it's a defensive coding, I doesn't break anything, but it could if we add some code later and forget to add the goto.. so I propose to leave it there
- }
+out:
- g_object_unref(auth_result);
- return result;
+}
comment please, because I haven't run it yet
crash-catcher@lists.fedorahosted.org