diff --git a/.accountsservice.metadata b/.accountsservice.metadata new file mode 100644 index 0000000..ac25f19 --- /dev/null +++ b/.accountsservice.metadata @@ -0,0 +1 @@ +915cf5df1ce04a2dfc6026ba58734f9cb77a3cae SOURCES/accountsservice-0.6.35.tar.xz diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/0001-Avoid-deleting-the-root-user.patch b/SOURCES/0001-Avoid-deleting-the-root-user.patch new file mode 100644 index 0000000..06c9b0c --- /dev/null +++ b/SOURCES/0001-Avoid-deleting-the-root-user.patch @@ -0,0 +1,51 @@ +From a9b7e9e368e79957ef492304bf62742b1304b7bb Mon Sep 17 00:00:00 2001 +From: Matthias Clasen +Date: Fri, 1 Nov 2013 17:09:25 -0400 +Subject: [PATCH] Avoid deleting the root user + +The check we have in place against deleting the root user can +be tricked by exploiting the fact that we are checking a gint64, +and then later cast it to a uid_t. This can be seen with the +following test, which will delete your root account: + +qdbus --system org.freedesktop.Accounts /org/freedesktop/Accounts \ + org.freedesktop.Accounts.DeleteUser -9223372036854775808 true + +Found with the dfuzzer tool, +https://github.com/matusmarhefka/dfuzzer +--- + src/daemon.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/daemon.c b/src/daemon.c +index 9c9f617..b2720f4 100644 +--- a/src/daemon.c ++++ b/src/daemon.c +@@ -1232,7 +1232,7 @@ daemon_uncache_user (AccountsAccounts *accounts, + } + + typedef struct { +- gint64 uid; ++ uid_t uid; + gboolean remove_files; + } DeleteUserData; + +@@ -1314,13 +1314,13 @@ daemon_delete_user (AccountsAccounts *accounts, + Daemon *daemon = (Daemon*)accounts; + DeleteUserData *data; + +- if (uid == 0) { ++ if ((uid_t)uid == 0) { + throw_error (context, ERROR_FAILED, "Refuse to delete root user"); + return TRUE; + } + + data = g_new0 (DeleteUserData, 1); +- data->uid = uid; ++ data->uid = (uid_t)uid; + data->remove_files = remove_files; + + daemon_local_check_auth (daemon, +-- +1.8.4.2 + diff --git a/SOURCES/rip-out-extension-interface.patch b/SOURCES/rip-out-extension-interface.patch new file mode 100644 index 0000000..b2f3483 --- /dev/null +++ b/SOURCES/rip-out-extension-interface.patch @@ -0,0 +1,868 @@ +From f86c93014e698d81d43fe1ebaf805fa794e5a984 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 22 Oct 2013 15:42:16 -0400 +Subject: [PATCH] daemon: rip out extension interface + +It requires newer glib than we're shipping +--- + configure.ac | 2 +- + src/Makefile.am | 1 - + src/daemon.c | 11 --- + src/daemon.h | 3 - + src/user.c | 273 -------------------------------------------------------- + 5 files changed, 1 insertion(+), 289 deletions(-) + +diff --git a/configure.ac b/configure.ac +index cb1fcda..a7f4e20 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1,58 +1,58 @@ + AC_INIT([AccountsService],[0.6.35]) + AM_INIT_AUTOMAKE(no-dist-gzip dist-xz tar-ustar foreign) + + GETTEXT_PACKAGE=accounts-service + AC_SUBST(GETTEXT_PACKAGE) + AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", + [the gettext translation domain]) + + # Support silent build rules, requires at least automake-1.11. Enable + # by either passing --enable-silent-rules to configure or passing V=0 + # to make + m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + + AC_USE_SYSTEM_EXTENSIONS + AC_PROG_CC + PKG_PROG_PKG_CONFIG + AM_GLIB_GNU_GETTEXT + IT_PROG_INTLTOOL([0.40.0]) + + LT_INIT + LT_CURRENT=0 + LT_REVISION=0 + LT_AGE=0 + AC_SUBST(LT_CURRENT) + AC_SUBST(LT_REVISION) + AC_SUBST(LT_AGE) + +-PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.37.3 gio-unix-2.0) ++PKG_CHECK_MODULES(GIO, gio-2.0 gio-unix-2.0) + PKG_CHECK_MODULES(POLKIT, gio-unix-2.0 polkit-gobject-1) + + AM_MAINTAINER_MODE([enable]) + + # client library dependencies + LIBACCOUNTSSERVICE_LIBS="$GIO_LIBS" + AC_SUBST(LIBACCOUNTSSERVICE_LIBS) + LIBACCOUNTSSERVICE_CFLAGS="$GIO_CFLAGS" + AC_SUBST(LIBACCOUNTSSERVICE_CFLAGS) + + GOBJECT_INTROSPECTION_CHECK([0.9.12]) + + dnl --------------------------------------------------------------------------- + dnl - Core configuration + dnl --------------------------------------------------------------------------- + + AC_ARG_ENABLE(admin-group, + [AS_HELP_STRING([--enable-admin-group],[Set group for administrative accounts @<:@default=auto@:>@])], + ,enable_admin_group=auto) + AS_IF([test x$enable_admin_group = xauto], [ + AC_CHECK_FILE(/etc/redhat-release, enable_admin_group=wheel) + AC_CHECK_FILE(/etc/debian_version, enable_admin_group=sudo) + AS_IF([test x$enable_admin_group = xauto], [ + enable_admin_group=wheel + ]) + ]) + AC_DEFINE_UNQUOTED([ADMIN_GROUP], ["$enable_admin_group"], [Define to the group for administrator users]) + + AC_ARG_ENABLE(user-heuristics, + [AS_HELP_STRING([--enable-user-heuristics],[Enable heuristics for guessing system vs. human users])], +diff --git a/src/Makefile.am b/src/Makefile.am +index 6940f2d..de57e7a 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -7,52 +7,51 @@ INCLUDES = \ + -DICONDIR=\"$(localstatedir)/lib/AccountsService/icons\" \ + -DUSERDIR=\"$(localstatedir)/lib/AccountsService/users\" \ + -I$(srcdir) \ + -I$(builddir) \ + $(POLKIT_CFLAGS) \ + $(WARN_CFLAGS) + + noinst_LTLIBRARIES = libaccounts-generated.la + + libaccounts_generated_la_SOURCES = \ + accounts-generated.c \ + accounts-generated.h \ + accounts-user-generated.c \ + accounts-user-generated.h \ + $(NULL) + BUILT_SOURCES += $(libaccounts_generated_la_SOURCES) + + accounts-generated.c accounts-generated.h: $(top_srcdir)/data/org.freedesktop.Accounts.xml Makefile + gdbus-codegen --generate-c-code accounts-generated --c-namespace Accounts --interface-prefix=org.freedesktop. $(top_srcdir)/data/org.freedesktop.Accounts.xml + + accounts-user-generated.c accounts-user-generated.h: $(top_srcdir)/data/org.freedesktop.Accounts.User.xml Makefile + gdbus-codegen --generate-c-code accounts-user-generated --c-namespace Accounts --interface-prefix=org.freedesktop.Accounts. $(top_srcdir)/data/org.freedesktop.Accounts.User.xml + + libexec_PROGRAMS = accounts-daemon + + accounts_daemon_SOURCES = \ + $(enums_h_sources) \ + types.h \ + daemon.h \ + daemon.c \ +- extensions.c \ + user-classify.h \ + user-classify.c \ + user.h \ + user.c \ + util.h \ + util.c \ + main.c + + accounts_daemon_LDADD = \ + libaccounts-generated.la \ + $(POLKIT_LIBS) + + CLEANFILES = \ + $(BUILT_SOURCES) \ + *.gcda \ + *.gcno \ + $(NULL) + + install-data-hook: + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/AccountsService/users" + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/AccountsService/icons" +diff --git a/src/daemon.c b/src/daemon.c +index 9c9f617..ea75190 100644 +--- a/src/daemon.c ++++ b/src/daemon.c +@@ -53,61 +53,60 @@ + #define PATH_GDM_CUSTOM "/etc/gdm/custom.conf" + #ifdef HAVE_UTMPX_H + #define PATH_WTMP _PATH_WTMPX + #endif + + enum { + PROP_0, + PROP_DAEMON_VERSION + }; + + struct DaemonPrivate { + GDBusConnection *bus_connection; + GDBusProxy *bus_proxy; + + GHashTable *users; + + User *autologin; + + GFileMonitor *passwd_monitor; + GFileMonitor *shadow_monitor; + GFileMonitor *group_monitor; + GFileMonitor *gdm_monitor; + #ifdef HAVE_UTMPX_H + GFileMonitor *wtmp_monitor; + #endif + + guint reload_id; + guint autologin_id; + + PolkitAuthority *authority; +- GHashTable *extension_ifaces; + }; + + typedef struct passwd * (* EntryGeneratorFunc) (GHashTable *, gpointer *); + + static void daemon_accounts_accounts_iface_init (AccountsAccountsIface *iface); + + G_DEFINE_TYPE_WITH_CODE (Daemon, daemon, ACCOUNTS_TYPE_ACCOUNTS_SKELETON, G_IMPLEMENT_INTERFACE (ACCOUNTS_TYPE_ACCOUNTS, daemon_accounts_accounts_iface_init)); + + #define DAEMON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_DAEMON, DaemonPrivate)) + + static const GDBusErrorEntry accounts_error_entries[] = + { + { ERROR_FAILED, "org.freedesktop.Accounts.Error.Failed" }, + { ERROR_USER_EXISTS, "org.freedesktop.Accounts.Error.UserExists" }, + { ERROR_USER_DOES_NOT_EXIST, "org.freedesktop.Accounts.Error.UserDoesNotExist" }, + { ERROR_PERMISSION_DENIED, "org.freedesktop.Accounts.Error.PermissionDenied" }, + { ERROR_NOT_SUPPORTED, "org.freedesktop.Accounts.Error.NotSupported" } + }; + + GQuark + error_quark (void) + { + static volatile gsize quark_volatile = 0; + + g_dbus_error_register_error_domain ("accounts_error", + &quark_volatile, + accounts_error_entries, + G_N_ELEMENTS (accounts_error_entries)); + + return (GQuark) quark_volatile; +@@ -656,107 +655,103 @@ setup_monitor (Daemon *daemon, + FileChangeCallback *callback) + { + GError *error = NULL; + GFile *file; + GFileMonitor *monitor; + + file = g_file_new_for_path (path); + monitor = g_file_monitor_file (file, + G_FILE_MONITOR_NONE, + NULL, + &error); + if (monitor != NULL) { + g_signal_connect (monitor, + "changed", + G_CALLBACK (callback), + daemon); + } else { + g_warning ("Unable to monitor %s: %s", path, error->message); + g_error_free (error); + } + g_object_unref (file); + + return monitor; + } + + static void + daemon_init (Daemon *daemon) + { + daemon->priv = DAEMON_GET_PRIVATE (daemon); + +- daemon->priv->extension_ifaces = daemon_read_extension_ifaces (); +- + daemon->priv->users = create_users_hash_table (); + + daemon->priv->passwd_monitor = setup_monitor (daemon, + PATH_PASSWD, + on_users_monitor_changed); + daemon->priv->shadow_monitor = setup_monitor (daemon, + PATH_SHADOW, + on_users_monitor_changed); + daemon->priv->group_monitor = setup_monitor (daemon, + PATH_GROUP, + on_users_monitor_changed); + + #ifdef HAVE_UTMPX_H + daemon->priv->wtmp_monitor = setup_monitor (daemon, + PATH_WTMP, + on_users_monitor_changed); + #endif + + daemon->priv->gdm_monitor = setup_monitor (daemon, + PATH_GDM_CUSTOM, + on_gdm_monitor_changed); + + queue_reload_users (daemon); + queue_reload_autologin (daemon); + } + + static void + daemon_finalize (GObject *object) + { + Daemon *daemon; + + g_return_if_fail (IS_DAEMON (object)); + + daemon = DAEMON (object); + + if (daemon->priv->bus_proxy != NULL) + g_object_unref (daemon->priv->bus_proxy); + + if (daemon->priv->bus_connection != NULL) + g_object_unref (daemon->priv->bus_connection); + + g_hash_table_destroy (daemon->priv->users); + +- g_hash_table_unref (daemon->priv->extension_ifaces); +- + G_OBJECT_CLASS (daemon_parent_class)->finalize (object); + } + + static gboolean + register_accounts_daemon (Daemon *daemon) + { + GError *error = NULL; + + daemon->priv->authority = polkit_authority_get_sync (NULL, &error); + + if (daemon->priv->authority == NULL) { + if (error != NULL) { + g_critical ("error getting polkit authority: %s", error->message); + g_error_free (error); + } + goto error; + } + + daemon->priv->bus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); + if (daemon->priv->bus_connection == NULL) { + if (error != NULL) { + g_critical ("error getting system bus: %s", error->message); + g_error_free (error); + } + goto error; + } + + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon), + daemon->priv->bus_connection, + "/org/freedesktop/Accounts", +@@ -1526,66 +1521,60 @@ daemon_local_set_automatic_login (Daemon *daemon, + { + if (daemon->priv->autologin == user && enabled) { + return TRUE; + } + + if (daemon->priv->autologin != user && !enabled) { + return TRUE; + } + + if (!save_autologin (daemon, user_get_user_name (user), enabled, error)) { + return FALSE; + } + + if (daemon->priv->autologin != NULL) { + g_object_set (daemon->priv->autologin, "automatic-login", FALSE, NULL); + g_signal_emit_by_name (daemon->priv->autologin, "changed", 0); + g_object_unref (daemon->priv->autologin); + daemon->priv->autologin = NULL; + } + + if (enabled) { + g_object_set (user, "automatic-login", TRUE, NULL); + g_signal_emit_by_name (user, "changed", 0); + g_object_ref (user); + daemon->priv->autologin = user; + } + + return TRUE; + } + +-GHashTable * +-daemon_get_extension_ifaces (Daemon *daemon) +-{ +- return daemon->priv->extension_ifaces; +-} +- + static void + get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) + { + switch (prop_id) { + case PROP_DAEMON_VERSION: + g_value_set_string (value, VERSION); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + + static void + set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) + { + switch (prop_id) { + case PROP_DAEMON_VERSION: + g_assert_not_reached (); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +diff --git a/src/daemon.h b/src/daemon.h +index b7e072e..e036407 100644 +--- a/src/daemon.h ++++ b/src/daemon.h +@@ -69,36 +69,33 @@ GQuark error_quark (void); + GType daemon_get_type (void) G_GNUC_CONST; + Daemon *daemon_new (void); + + /* local methods */ + + User *daemon_local_find_user_by_id (Daemon *daemon, + uid_t uid); + User *daemon_local_find_user_by_name (Daemon *daemon, + const gchar *name); + User *daemon_local_get_automatic_login_user (Daemon *daemon); + + typedef void (*AuthorizedCallback) (Daemon *daemon, + User *user, + GDBusMethodInvocation *context, + gpointer data); + + void daemon_local_check_auth (Daemon *daemon, + User *user, + const gchar *action_id, + gboolean allow_interaction, + AuthorizedCallback auth_cb, + GDBusMethodInvocation *context, + gpointer data, + GDestroyNotify destroy_notify); + + gboolean daemon_local_set_automatic_login (Daemon *daemon, + User *user, + gboolean enabled, + GError **error); + +-GHashTable * daemon_read_extension_ifaces (void); +-GHashTable * daemon_get_extension_ifaces (Daemon *daemon); +- + G_END_DECLS + + #endif /* __DAEMON_H__ */ +diff --git a/src/user.c b/src/user.c +index 1698eeb..163d136 100644 +--- a/src/user.c ++++ b/src/user.c +@@ -77,63 +77,60 @@ struct User { + + GDBusConnection *system_bus_connection; + gchar *object_path; + + Daemon *daemon; + + GKeyFile *keyfile; + + uid_t uid; + gid_t gid; + gchar *user_name; + gchar *real_name; + AccountType account_type; + PasswordMode password_mode; + gchar *password_hint; + gchar *home_dir; + gchar *shell; + gchar *email; + gchar *language; + gchar *x_session; + gchar *location; + guint64 login_frequency; + gint64 login_time; + GVariant *login_history; + gchar *icon_file; + gchar *default_icon_file; + gboolean locked; + gboolean automatic_login; + gboolean system_account; + gboolean local_account; +- +- guint *extension_ids; +- guint n_extension_ids; + }; + + typedef struct UserClass + { + AccountsUserSkeletonClass parent_class; + } UserClass; + + static void user_accounts_user_iface_init (AccountsUserIface *iface); + + G_DEFINE_TYPE_WITH_CODE (User, user, ACCOUNTS_TYPE_USER_SKELETON, G_IMPLEMENT_INTERFACE (ACCOUNTS_TYPE_USER, user_accounts_user_iface_init)); + + static gint + account_type_from_pwent (struct passwd *pwent) + { + struct group *grp; + gid_t wheel; + gid_t *groups; + gint ngroups; + gint i; + + if (pwent->pw_uid == 0) { + g_debug ("user is root so account type is administrator"); + return ACCOUNT_TYPE_ADMINISTRATOR; + } + + grp = getgrnam (ADMIN_GROUP); + if (grp == NULL) { + g_debug (ADMIN_GROUP " group not found"); + return ACCOUNT_TYPE_STANDARD; + } +@@ -436,379 +433,109 @@ save_extra_data (User *user) + user->user_name, + NULL); + g_file_set_contents (filename, data, -1, &error); + g_free (filename); + } + if (error) { + g_warning ("Saving data for user %s failed: %s", + user->user_name, error->message); + g_error_free (error); + } + } + + static void + move_extra_data (const gchar *old_name, + const gchar *new_name) + { + gchar *old_filename; + gchar *new_filename; + + old_filename = g_build_filename (USERDIR, + old_name, NULL); + new_filename = g_build_filename (USERDIR, + new_name, NULL); + + g_rename (old_filename, new_filename); + + g_free (old_filename); + g_free (new_filename); + } + +-static GVariant * +-user_extension_get_value (User *user, +- GDBusInterfaceInfo *interface, +- const GDBusPropertyInfo *property) +-{ +- const GVariantType *type = G_VARIANT_TYPE (property->signature); +- GVariant *value; +- gchar *printed; +- gint i; +- +- /* First, try to get the value from the keyfile */ +- printed = g_key_file_get_value (user->keyfile, interface->name, property->name, NULL); +- if (printed) { +- value = g_variant_parse (type, printed, NULL, NULL, NULL); +- g_free (printed); +- +- if (value != NULL) +- return value; +- } +- +- /* If that didn't work, try for a default value annotation */ +- for (i = 0; property->annotations && property->annotations[i]; i++) { +- GDBusAnnotationInfo *annotation = property->annotations[i]; +- +- if (g_str_equal (annotation->key, "org.freedesktop.Accounts.DefaultValue.String")) { +- if (g_str_equal (property->signature, "s")) +- return g_variant_ref_sink (g_variant_new_string (annotation->value)); +- } +- else if (g_str_equal (annotation->key, "org.freedesktop.Accounts.DefaultValue")) { +- value = g_variant_parse (type, annotation->value, NULL, NULL, NULL); +- if (value != NULL) +- return value; +- } +- } +- +- /* Nothing found... */ +- return NULL; +-} +- +-static void +-user_extension_get_property (User *user, +- Daemon *daemon, +- GDBusInterfaceInfo *interface, +- GDBusMethodInvocation *invocation) +-{ +- const GDBusPropertyInfo *property = g_dbus_method_invocation_get_property_info (invocation); +- GVariant *value; +- +- value = user_extension_get_value (user, interface, property); +- +- if (value) { +- g_dbus_method_invocation_return_value (invocation, g_variant_new ("(v)", value)); +- g_variant_unref (value); +- } +- else { +- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, +- "Key '%s' is not set and has no default value", +- property->name); +- } +-} +- +-static void +-user_extension_get_all_properties (User *user, +- Daemon *daemon, +- GDBusInterfaceInfo *interface, +- GDBusMethodInvocation *invocation) +-{ +- GVariantBuilder builder; +- gint i; +- +- g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); +- for (i = 0; interface->properties && interface->properties[i]; i++) { +- GDBusPropertyInfo *property = interface->properties[i]; +- GVariant *value; +- +- value = user_extension_get_value (user, interface, property); +- +- if (value) { +- g_variant_builder_add (&builder, "{sv}", property->name, value); +- g_variant_unref (value); +- } +- } +- +- g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{sv})", &builder)); +-} +- +-static void +-user_extension_set_property (User *user, +- Daemon *daemon, +- GDBusInterfaceInfo *interface, +- GDBusMethodInvocation *invocation) +-{ +- const GDBusPropertyInfo *property = g_dbus_method_invocation_get_property_info (invocation); +- GVariant *value; +- gchar *printed; +- gchar *prev; +- +- g_variant_get_child (g_dbus_method_invocation_get_parameters (invocation), 2, "v", &value); +- +- /* We'll always have the type when we parse it back so +- * we don't need it to be printed with annotations. +- */ +- printed = g_variant_print (value, FALSE); +- +- /* May as well try to avoid the thrashing... */ +- prev = g_key_file_get_value (user->keyfile, interface->name, property->name, NULL); +- +- if (!prev || !g_str_equal (printed, prev)) { +- g_key_file_set_value (user->keyfile, interface->name, property->name, printed); +- +- /* Emit a change signal. Use invalidation +- * because the data may not be world-readable. +- */ +- g_dbus_connection_emit_signal (g_dbus_method_invocation_get_connection (invocation), +- NULL, /* destination_bus_name */ +- g_dbus_method_invocation_get_object_path (invocation), +- "org.freedesktop.DBus.Properties", "PropertiesChanged", +- g_variant_new_parsed ("( %s, %a{sv}, [ %s ] )", +- interface->name, NULL, property->name), +- NULL); +- +- accounts_user_emit_changed (ACCOUNTS_USER (user)); +- save_extra_data (user); +- } +- +- g_variant_unref (value); +- g_free (printed); +- g_free (prev); +- +- g_dbus_method_invocation_return_value (invocation, g_variant_new ("()")); +-} +- +-static void +-user_extension_authentication_done (Daemon *daemon, +- User *user, +- GDBusMethodInvocation *invocation, +- gpointer user_data) +-{ +- GDBusInterfaceInfo *interface = user_data; +- const gchar *method_name; +- +- method_name = g_dbus_method_invocation_get_method_name (invocation); +- +- if (g_str_equal (method_name, "Get")) +- user_extension_get_property (user, daemon, interface, invocation); +- else if (g_str_equal (method_name, "GetAll")) +- user_extension_get_all_properties (user, daemon, interface, invocation); +- else if (g_str_equal (method_name, "Set")) +- user_extension_set_property (user, daemon, interface, invocation); +- else +- g_assert_not_reached (); +-} +- +-static void +-user_extension_method_call (GDBusConnection *connection, +- const gchar *sender, +- const gchar *object_path, +- const gchar *interface_name, +- const gchar *method_name, +- GVariant *parameters, +- GDBusMethodInvocation *invocation, +- gpointer user_data) +-{ +- User *user = user_data; +- GDBusInterfaceInfo *iface_info; +- const gchar *annotation_name; +- const gchar *action_id; +- gint uid; +- gint i; +- +- /* We don't allow method calls on extension interfaces, so we +- * should only ever see property calls here. +- */ +- g_assert_cmpstr (interface_name, ==, "org.freedesktop.DBus.Properties"); +- +- /* Now get the real interface name */ +- g_variant_get_child (parameters, 0, "&s", &interface_name); +- +- if (get_caller_uid (invocation, &uid) && (uid_t) uid == user->uid) { +- /* Operation on sender's own User object */ +- if (g_str_equal (method_name, "Set")) { +- annotation_name = "org.freedesktop.Accounts.Authentication.ChangeOwn"; +- action_id = "org.freedesktop.accounts.change-own-user-data"; +- } +- else { +- annotation_name = "org.freedesktop.Accounts.Authentication.ReadOwn"; +- action_id = ""; /* reading allowed by default */ +- } +- } +- else { +- /* Operation on someone else's User object */ +- if (g_str_equal (method_name, "Set")) { +- annotation_name = "org.freedesktop.Accounts.Authentication.ChangeAny"; +- action_id = "org.freedesktop.accounts.user-administration"; +- } +- else { +- annotation_name = "org.freedesktop.Accounts.Authentication.ReadAny"; +- action_id = ""; /* reading allowed by default */ +- } +- } +- +- iface_info = g_hash_table_lookup (daemon_get_extension_ifaces (user->daemon), interface_name); +- g_assert (iface_info != NULL); +- +- for (i = 0; iface_info->annotations && iface_info->annotations[i]; i++) { +- if (g_str_equal (iface_info->annotations[i]->key, annotation_name)) { +- action_id = iface_info->annotations[i]->value; +- break; +- } +- } +- +- if (action_id[0] == '\0') { +- /* Should always allow this call, so just do it now */ +- user_extension_authentication_done (user->daemon, user, invocation, iface_info); +- } +- else { +- daemon_local_check_auth (user->daemon, user, action_id, TRUE, +- user_extension_authentication_done, +- invocation, iface_info, NULL); +- } +-} +- +-static void +-user_register_extensions (User *user) +-{ +- static const GDBusInterfaceVTable vtable = { +- user_extension_method_call, +- NULL /* get_property */, +- NULL /* set_property */ +- }; +- GHashTable *extensions; +- GHashTableIter iter; +- gpointer iface; +- gint i = 0; +- +- g_assert (user->extension_ids == NULL); +- g_assert (user->n_extension_ids == 0); +- +- extensions = daemon_get_extension_ifaces (user->daemon); +- user->n_extension_ids = g_hash_table_size (extensions); +- user->extension_ids = g_new (guint, user->n_extension_ids); +- g_hash_table_iter_init (&iter, extensions); +- +- /* Ignore errors when registering more interfaces because (a) +- * they won't happen and (b) even if they do, we still want to +- * publish the main user interface. +- */ +- while (g_hash_table_iter_next (&iter, NULL, &iface)) +- user->extension_ids[i++] = g_dbus_connection_register_object (user->system_bus_connection, +- user->object_path, iface, +- &vtable, user, NULL, NULL); +-} +- + static gchar * + compute_object_path (User *user) + { + gchar *object_path; + + object_path = g_strdup_printf ("/org/freedesktop/Accounts/User%ld", + (long) user->uid); + + return object_path; + } + + void + user_register (User *user) + { + GError *error = NULL; + + user->system_bus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); + if (user->system_bus_connection == NULL) { + if (error != NULL) { + g_critical ("error getting system bus: %s", error->message); + g_error_free (error); + } + return; + } + + user->object_path = compute_object_path (user); + + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (user), + user->system_bus_connection, + user->object_path, + &error)) { + if (error != NULL) { + g_critical ("error exporting user object: %s", error->message); + g_error_free (error); + } + return; + } +- +- user_register_extensions (user); + } + + void + user_save (User *user) + { + save_extra_data (user); + } + + void + user_unregister (User *user) + { + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (user)); +- +- if (user->extension_ids) { +- guint i; +- +- for (i = 0; i < user->n_extension_ids; i++) { +- /* In theory, if an error happened during registration, we could have 0 here. */ +- if (user->extension_ids[i] == 0) +- continue; +- +- g_dbus_connection_unregister_object (user->system_bus_connection, user->extension_ids[i]); +- } +- +- g_clear_pointer (&user->extension_ids, g_free); +- user->n_extension_ids = 0; +- } + } + + void + user_changed (User *user) + { + accounts_user_emit_changed (ACCOUNTS_USER (user)); + } + + User * + user_new (Daemon *daemon, + uid_t uid) + { + User *user; + + user = g_object_new (TYPE_USER, NULL); + user->daemon = daemon; + user->uid = uid; + + return user; + } + + const gchar * + user_get_user_name (User *user) + { + return user->user_name; + } + + gboolean + user_get_system_account (User *user) + { +-- +1.8.3.1 + diff --git a/SPECS/accountsservice.spec b/SPECS/accountsservice.spec new file mode 100644 index 0000000..f86b7e4 --- /dev/null +++ b/SPECS/accountsservice.spec @@ -0,0 +1,247 @@ +%global _hardened_build 1 + +Name: accountsservice +Version: 0.6.35 +Release: 2%{?dist} +Summary: D-Bus interfaces for querying and manipulating user account information + +Group: System Environment/Daemons +License: GPLv3+ +URL: http://www.fedoraproject.org/wiki/Features/UserAccountDialog +#VCS: git:git://git.freedesktop.org/accountsservice +Source0: http://www.freedesktop.org/software/accountsservice/accountsservice-%{version}.tar.xz + +BuildRequires: glib2-devel +BuildRequires: dbus-glib-devel +BuildRequires: polkit-devel +BuildRequires: intltool +BuildRequires: systemd-units +BuildRequires: systemd-devel +BuildRequires: gobject-introspection-devel +BuildRequires: automake, autoconf, libtool +BuildRequires: gtk-doc + +Requires: polkit +Requires: shadow-utils + +Requires(post): systemd-units +Requires(preun): systemd-units +Requires(postun): systemd-units + +Patch0: rip-out-extension-interface.patch +Patch1: 0001-Avoid-deleting-the-root-user.patch + +%package libs +Summary: Client-side library to talk to accountsservice +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description libs +The accountsservice-libs package contains a library that can +be used by applications that want to interact with the accountsservice +daemon. + + +%package devel +Summary: Development files for accountsservice-libs +Group: Development/Libraries +Requires: %{name}-libs = %{version}-%{release} + +%description devel +The accountsservice-devel package contains headers and other +files needed to build applications that use accountsservice-libs. + + +%description +The accountsservice project provides a set of D-Bus interfaces for +querying and manipulating user account information and an implementation +of these interfaces, based on the useradd, usermod and userdel commands. + + +%prep +%setup -q +%patch0 -p1 -b .rip-out-extension-interface +%patch1 -p1 -b .dont-delete-root + +%build +autoreconf -f -i +%configure +make %{?_smp_mflags} + + +%install +make install DESTDIR=$RPM_BUILD_ROOT +rm $RPM_BUILD_ROOT%{_libdir}/*.la +rm $RPM_BUILD_ROOT%{_libdir}/*.a +%find_lang accounts-service + + +%post libs -p /sbin/ldconfig + +%postun libs -p /sbin/ldconfig + +%post +%systemd_post accounts-daemon.service + +%preun +%systemd_preun accounts-daemon.service + +%postun +%systemd_postun accounts-daemon.service + +%files -f accounts-service.lang +%defattr(-,root,root,-) +%doc COPYING README AUTHORS +%{_sysconfdir}/dbus-1/system.d/org.freedesktop.Accounts.conf +%{_libexecdir}/accounts-daemon +%{_datadir}/dbus-1/interfaces/org.freedesktop.Accounts.xml +%{_datadir}/dbus-1/interfaces/org.freedesktop.Accounts.User.xml +%{_datadir}/dbus-1/system-services/org.freedesktop.Accounts.service +%{_datadir}/polkit-1/actions/org.freedesktop.accounts.policy +%dir %{_localstatedir}/lib/AccountsService/ +%dir %{_localstatedir}/lib/AccountsService/users +%dir %{_localstatedir}/lib/AccountsService/icons +%{_unitdir}/accounts-daemon.service + +%files libs +%{_libdir}/libaccountsservice.so.* +%{_libdir}/girepository-1.0/AccountsService-1.0.typelib + +%files devel +%{_includedir}/accountsservice-1.0 +%{_libdir}/libaccountsservice.so +%{_libdir}/pkgconfig/accountsservice.pc +%{_datadir}/gir-1.0/AccountsService-1.0.gir +%dir %{_datadir}/gtk-doc/html/libaccountsservice +%{_datadir}/gtk-doc/html/libaccountsservice/* + +%changelog +* Fri Nov 1 2013 Matthias Clasen 0.6.35-2 +- Refuse to delete the root user +- Resolves: #1002973 + +* Tue Oct 22 2013 Ray Strode 0.6.35-1 +- Update to 0.6.35 + Resolves: #1019488 + +* Tue Jun 11 2013 Ray Strode 0.6.34-1 +- Update to 0.6.34 + +* Tue Jun 11 2013 Matthias Clasen - 0.6.33-1 +- Update to 0.6.33 + +* Tue May 14 2013 Matthias Clasen - 0.6.32-1 +- Update to 0.6.32 + +* Thu Apr 18 2013 Matthias Clasen - 0.6.31-2 +- Hardened build + +* Tue Apr 16 2013 Matthias Clasen - 0.6.31-1 +- Update to 0.6.31 + +* Wed Feb 13 2013 Fedora Release Engineering - 0.6.30-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Wed Jan 16 2013 Richard Hughes - 0.6.30-1 +- Update to 0.6.30 + +* Fri Nov 16 2012 Matthias Clasen - 0.6.26-1 +- Update to 0.6.26 + +* Tue Oct 2 2012 Matthias Clasen - 0.6.25-2 +- Update to 0.6.25 +- Use systemd scriptlets (#856649) + +* Wed Jul 18 2012 Fedora Release Engineering - 0.6.22-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Sat Jul 14 2012 Ville Skyttä - 0.6.22-2 +- Add ldconfig scriptlets to -libs. + +* Thu Jun 28 2012 Ray Strode 0.6.22-1 +- Update to 0.6.22. +- Fixes CVE-2012-2737 - local file disclosure + Related: #832532 + +* Thu May 30 2012 Matthias Clasen 0.6.21-1 +- Update to 0.6.21 + +* Fri May 04 2012 Ray Strode 0.6.20-1 +- Update to 0.6.20. Should fix user list. + Related: #814690 + +* Thu May 03 2012 Ray Strode 0.6.19-1 +- Update to 0.6.19 + Allows user deletion of logged in users + Related: #814690 + +* Wed Apr 11 2012 Matthias Clasen - 0.6.18-1 +- Update to 0.6.18 + +* Tue Mar 27 2012 Ray Strode 0.6.17-1 +- Update to latest release + +* Sun Mar 4 2012 Peter Robinson - 0.6.15-4 +- Fix unitdir with usrmove + +* Thu Jan 12 2012 Fedora Release Engineering - 0.6.15-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Nov 29 2011 Matthias Clasen 0.6.15-2 +- Make resetting user icons work +- Update to 0.6.15 +- Fixes session chooser at login screen when logged into vt + +* Wed Sep 21 2011 Ray Strode 0.6.14-2 +- Fix wtmp loading so users coming from the network are + remembered in the user list in subsequent boots + +* Wed Sep 21 2011 Ray Strode 0.6.14-1 +- Update to 0.6.14 + +* Sun Sep 4 2011 Matthias Clasen - 0.6.13-3 +- Fix fast user switching + +* Mon Aug 15 2011 Kalev Lember - 0.6.13-2 +- Rebuilt for rpm bug #728707 + +* Tue Jul 19 2011 Matthias Clasen - 0.6.13-1 +- Update to 0.6.13 +- Drop ConsoleKit dependency + +* Mon Jun 06 2011 Ray Strode 0.6.12-1 +- Update to latest release + +* Wed May 18 2011 Matthias Clasen 0.6.11-1 +- Update to 0.6.11 + +* Mon Feb 07 2011 Fedora Release Engineering - 0.6.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Feb 02 2011 Ray Strode 0.6.3-1 +- Update to 0.6.3 + +* Thu Jan 27 2011 Matthias Clasen 0.6.2-1 +- Update to 0.6.2 + +* Wed Jul 21 2010 Matthias Clasen 0.6.1-1 +- Update to 0.6.1 +- Install systemd unit file + +* Mon Apr 5 2010 Matthias Clasen 0.6-2 +- Always emit changed signal on icon change + +* Tue Mar 30 2010 Matthias Clasen 0.6-1 +- Update to 0.6 + +* Mon Mar 22 2010 Matthias Clasen 0.5-1 +- Update to 0.5 + +* Mon Feb 22 2010 Bastien Nocera 0.4-3 +- Fix directory ownership + +* Mon Feb 22 2010 Bastien Nocera 0.4-2 +- Add missing directories to the filelist + +* Fri Jan 29 2010 Matthias Clasen 0.4-1 +- Initial packaging, based on work by Richard Hughes