--- accountsservice-0.6.37/debian/changelog 2014-11-19 03:07:39.000000000 +1100 +++ accountsservice-0.6.40/debian/changelog 2015-01-25 14:48:16.000000000 +1100 @@ -1,3 +1,16 @@ +accountsservice (0.6.40-0ubuntu1) vivid; urgency=medium + + * New upstream release + * debian/libaccountsservice0.symbols: Add new symbols + * debian/patches: Refreshed + - 0007-add-lightdm-support.patch + - 0021-support-extrausers.patch + - 0022-fix-desktop-centric-polkit-policy.patch: dropped included in + new version + - delete unused patches + + -- Tim Lunn Sun, 25 Jan 2015 13:10:24 +1100 + accountsservice (0.6.37-1ubuntu10) vivid; urgency=medium * No change rebuild to get debug symbols on all architectures. --- accountsservice-0.6.37/debian/libaccountsservice0.symbols 2014-06-24 13:37:08.000000000 +1000 +++ accountsservice-0.6.40/debian/libaccountsservice0.symbols 2015-01-25 14:23:57.000000000 +1100 @@ -71,6 +71,9 @@ accounts_user_call_set_icon_file@Base 0.6.18 accounts_user_call_set_icon_file_finish@Base 0.6.18 accounts_user_call_set_icon_file_sync@Base 0.6.18 + accounts_user_call_set_input_sources@Base 0.6.40 + accounts_user_call_set_input_sources_finish@Base 0.6.40 + accounts_user_call_set_input_sources_sync@Base 0.6.40 accounts_user_call_set_language@Base 0.6.18 accounts_user_call_set_language_finish@Base 0.6.18 accounts_user_call_set_language_sync@Base 0.6.18 @@ -113,6 +116,7 @@ accounts_user_complete_set_formats_locale@Base 0.6.29 accounts_user_complete_set_home_directory@Base 0.6.18 accounts_user_complete_set_icon_file@Base 0.6.18 + accounts_user_complete_set_input_sources@Base 0.6.40 accounts_user_complete_set_language@Base 0.6.18 accounts_user_complete_set_location@Base 0.6.18 accounts_user_complete_set_locked@Base 0.6.18 @@ -129,6 +133,7 @@ accounts_user_dup_formats_locale@Base 0.6.29 accounts_user_dup_home_directory@Base 0.6.18 accounts_user_dup_icon_file@Base 0.6.18 + accounts_user_dup_input_sources@Base 0.6.40 accounts_user_dup_language@Base 0.6.18 accounts_user_dup_location@Base 0.6.18 accounts_user_dup_login_history@Base 0.6.29 @@ -146,6 +151,7 @@ accounts_user_get_formats_locale@Base 0.6.29 accounts_user_get_home_directory@Base 0.6.18 accounts_user_get_icon_file@Base 0.6.18 + accounts_user_get_input_sources@Base 0.6.40 accounts_user_get_language@Base 0.6.18 accounts_user_get_local_account@Base 0.6.24 accounts_user_get_location@Base 0.6.18 @@ -180,6 +186,7 @@ accounts_user_set_formats_locale@Base 0.6.29 accounts_user_set_home_directory@Base 0.6.18 accounts_user_set_icon_file@Base 0.6.18 + accounts_user_set_input_sources@Base 0.6.40 accounts_user_set_language@Base 0.6.18 accounts_user_set_local_account@Base 0.6.24 accounts_user_set_location@Base 0.6.18 @@ -208,6 +215,7 @@ act_user_get_formats_locale@Base 0.6.29 act_user_get_home_dir@Base 0.6.8 act_user_get_icon_file@Base 0.6.8 + act_user_get_input_sources@Base 0.6.40 act_user_get_language@Base 0.6.8 act_user_get_location@Base 0.6.8 act_user_get_locked@Base 0.6.8 @@ -255,6 +263,8 @@ act_user_manager_list_users@Base 0.6.8 act_user_manager_no_service@Base 0.6.34 act_user_manager_uncache_user@Base 0.6.24 + act_user_manager_uncache_user_async@Base 0.6.40 + act_user_manager_uncache_user_finish@Base 0.6.40 act_user_password_mode_get_type@Base 0.6.8 act_user_password_type_get_type@Base 0.6.29 act_user_set_account_type@Base 0.6.8 @@ -263,6 +273,7 @@ act_user_set_email@Base 0.6.8 act_user_set_formats_locale@Base 0.6.29 act_user_set_icon_file@Base 0.6.8 + act_user_set_input_sources@Base 0.6.40 act_user_set_language@Base 0.6.8 act_user_set_location@Base 0.6.8 act_user_set_locked@Base 0.6.8 --- accountsservice-0.6.37/debian/patches/0007-add-lightdm-support.patch 2014-06-24 13:37:08.000000000 +1000 +++ accountsservice-0.6.40/debian/patches/0007-add-lightdm-support.patch 2015-01-25 13:38:03.000000000 +1100 @@ -8,10 +8,10 @@ src/daemon.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 132 insertions(+), 11 deletions(-) -Index: b/src/daemon.c +Index: accountsservice-0.6.40/src/daemon.c =================================================================== ---- a/src/daemon.c -+++ b/src/daemon.c +--- accountsservice-0.6.40.orig/src/daemon.c ++++ accountsservice-0.6.40/src/daemon.c @@ -49,6 +49,7 @@ #define PATH_SHADOW "/etc/shadow" #define PATH_GROUP "/etc/group" @@ -20,7 +20,7 @@ enum { PROP_0, -@@ -67,6 +68,7 @@ +@@ -67,6 +68,7 @@ struct DaemonPrivate { GFileMonitor *shadow_monitor; GFileMonitor *group_monitor; GFileMonitor *gdm_monitor; @@ -28,13 +28,13 @@ GFileMonitor *wtmp_monitor; guint reload_id; -@@ -534,9 +536,19 @@ - wtmp_helper_get_path_for_monitor (), - on_users_monitor_changed); - -- daemon->priv->gdm_monitor = setup_monitor (daemon, -- PATH_GDM_CUSTOM, -- on_gdm_monitor_changed); +@@ -530,9 +532,19 @@ daemon_init (Daemon *daemon) + PATH_GROUP, + on_users_monitor_changed); + +- daemon->priv->wtmp_monitor = setup_monitor (daemon, +- wtmp_helper_get_path_for_monitor (), +- on_users_monitor_changed); + if (g_file_test ("/etc/gdm", G_FILE_TEST_EXISTS)) + { + daemon->priv->gdm_monitor = setup_monitor (daemon, @@ -49,9 +49,9 @@ + on_gdm_monitor_changed); + } - queue_reload_users (daemon); - queue_reload_autologin (daemon); -@@ -1267,10 +1279,10 @@ + daemon->priv->gdm_monitor = setup_monitor (daemon, + PATH_GDM_CUSTOM, +@@ -1266,10 +1278,10 @@ daemon_local_check_auth (Daemon } gboolean @@ -66,7 +66,7 @@ { GKeyFile *keyfile; GError *local_error; -@@ -1313,23 +1325,90 @@ +@@ -1312,23 +1324,90 @@ load_autologin (Daemon *daemon, return TRUE; } @@ -164,7 +164,7 @@ } g_key_file_set_string (keyfile, "daemon", "AutomaticLoginEnable", enabled ? "True" : "False"); -@@ -1344,6 +1423,58 @@ +@@ -1343,6 +1422,58 @@ save_autologin (Daemon *daemon, return result; } --- accountsservice-0.6.37/debian/patches/0021-support-extrausers.patch 2014-07-19 05:58:57.000000000 +1000 +++ accountsservice-0.6.40/debian/patches/0021-support-extrausers.patch 2015-01-25 14:18:37.000000000 +1100 @@ -1,8 +1,8 @@ -Index: accountsservice-0.6.37/src/daemon.c +Index: accountsservice-0.6.40/src/daemon.c =================================================================== ---- accountsservice-0.6.37.orig/src/daemon.c -+++ accountsservice-0.6.37/src/daemon.c -@@ -48,6 +48,9 @@ +--- accountsservice-0.6.40.orig/src/daemon.c ++++ accountsservice-0.6.40/src/daemon.c +@@ -48,6 +47,9 @@ #define PATH_PASSWD "/etc/passwd" #define PATH_SHADOW "/etc/shadow" #define PATH_GROUP "/etc/group" @@ -12,7 +12,7 @@ #define PATH_GDM_CUSTOM "/etc/gdm/custom.conf" #define PATH_LIGHTDM_CONFIG "/etc/lightdm/lightdm.conf" -@@ -67,6 +70,9 @@ struct DaemonPrivate { +@@ -67,6 +69,9 @@ struct DaemonPrivate { GFileMonitor *passwd_monitor; GFileMonitor *shadow_monitor; GFileMonitor *group_monitor; @@ -22,7 +22,7 @@ GFileMonitor *gdm_monitor; GFileMonitor *lightdm_monitor; GFileMonitor *wtmp_monitor; -@@ -554,6 +560,16 @@ daemon_init (Daemon *daemon) +@@ -554,6 +559,16 @@ daemon_init (Daemon *daemon) PATH_GROUP, on_users_monitor_changed); @@ -36,6 +36,6 @@ + PATH_EXTRAUSERS_GROUP, + on_users_monitor_changed); + - daemon->priv->wtmp_monitor = setup_monitor (daemon, - wtmp_helper_get_path_for_monitor (), - on_users_monitor_changed); + if (g_file_test ("/etc/gdm", G_FILE_TEST_EXISTS)) + { + daemon->priv->gdm_monitor = setup_monitor (daemon, --- accountsservice-0.6.37/debian/patches/1001-buildsystem.patch 2014-06-24 13:37:08.000000000 +1000 +++ accountsservice-0.6.40/debian/patches/1001-buildsystem.patch 1970-01-01 10:00:00.000000000 +1000 @@ -1,227 +0,0 @@ -Description: Add po/Makefile.in.in to prevent FTBFS. -From: http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/natty/lightdm/natty/view/head:/po/Makefile.in.in -Forwarded: no ---- - po/Makefile.in.in | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 217 insertions(+) - ---- /dev/null -+++ accountsservice/po/Makefile.in.in -@@ -0,0 +1,217 @@ -+# Makefile for program source directory in GNU NLS utilities package. -+# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper -+# Copyright (C) 2004-2008 Rodney Dawes -+# -+# This file may be copied and used freely without restrictions. It may -+# be used in projects which are not available under a GNU Public License, -+# but which still want to provide support for the GNU gettext functionality. -+# -+# - Modified by Owen Taylor to use GETTEXT_PACKAGE -+# instead of PACKAGE and to look for po2tbl in ./ not in intl/ -+# -+# - Modified by jacob berkman to install -+# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize -+# -+# - Modified by Rodney Dawes for use with intltool -+# -+# We have the following line for use by intltoolize: -+# INTLTOOL_MAKEFILE -+ -+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -+PACKAGE = @PACKAGE@ -+VERSION = @VERSION@ -+ -+SHELL = @SHELL@ -+ -+srcdir = @srcdir@ -+top_srcdir = @top_srcdir@ -+top_builddir = @top_builddir@ -+VPATH = @srcdir@ -+ -+prefix = @prefix@ -+exec_prefix = @exec_prefix@ -+datadir = @datadir@ -+datarootdir = @datarootdir@ -+libdir = @libdir@ -+DATADIRNAME = @DATADIRNAME@ -+itlocaledir = $(prefix)/$(DATADIRNAME)/locale -+subdir = po -+install_sh = @install_sh@ -+# Automake >= 1.8 provides @mkdir_p@. -+# Until it can be supposed, use the safe fallback: -+mkdir_p = $(install_sh) -d -+ -+INSTALL = @INSTALL@ -+INSTALL_DATA = @INSTALL_DATA@ -+ -+GMSGFMT = @GMSGFMT@ -+MSGFMT = @MSGFMT@ -+XGETTEXT = @XGETTEXT@ -+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -+MSGMERGE = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist -+GENPOT = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot -+ -+ALL_LINGUAS = @ALL_LINGUAS@ -+ -+PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; else echo "$(ALL_LINGUAS)"; fi) -+ -+USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep \^$$lang$$ $(srcdir)/LINGUAS 2>/dev/null`" -o -n "`echo $$ALINGUAS|tr ' ' '\n'|grep \^$$lang$$`"; then printf "$$lang "; fi; done; fi) -+ -+USE_LINGUAS=$(shell if test -n "$(USER_LINGUAS)" -o -n "$(LINGUAS)"; then LLINGUAS="$(USER_LINGUAS)"; else if test -n "$(PO_LINGUAS)"; then LLINGUAS="$(PO_LINGUAS)"; else LLINGUAS="$(ALL_LINGUAS)"; fi; fi; for lang in $$LLINGUAS; do printf "$$lang "; done) -+ -+POFILES=$(shell LINGUAS="$(PO_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.po "; done) -+ -+DISTFILES = Makefile.in.in POTFILES.in $(POFILES) -+EXTRA_DISTFILES = ChangeLog POTFILES.skip Makevars LINGUAS -+ -+POTFILES = \ -+# This comment gets stripped out -+ -+CATALOGS=$(shell LINGUAS="$(USE_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.gmo "; done) -+ -+.SUFFIXES: -+.SUFFIXES: .po .pox .gmo .mo .msg .cat -+ -+.po.pox: -+ $(MAKE) $(GETTEXT_PACKAGE).pot -+ $(MSGMERGE) $< $(GETTEXT_PACKAGE).pot -o $*.pox -+ -+.po.mo: -+ $(MSGFMT) -o $@ $< -+ -+.po.gmo: -+ file=`echo $* | sed 's,.*/,,'`.gmo \ -+ && rm -f $$file && $(GMSGFMT) -o $$file $< -+ -+.po.cat: -+ sed -f ../intl/po2msg.sed < $< > $*.msg \ -+ && rm -f $@ && gencat $@ $*.msg -+ -+ -+all: all-@USE_NLS@ -+ -+all-yes: $(CATALOGS) -+all-no: -+ -+$(GETTEXT_PACKAGE).pot: $(POTFILES) -+ $(GENPOT) -+ -+install: install-data -+install-data: install-data-@USE_NLS@ -+install-data-no: all -+install-data-yes: all -+ linguas="$(USE_LINGUAS)"; \ -+ for lang in $$linguas; do \ -+ dir=$(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES; \ -+ $(mkdir_p) $$dir; \ -+ if test -r $$lang.gmo; then \ -+ $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ -+ echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \ -+ else \ -+ $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ -+ echo "installing $(srcdir)/$$lang.gmo as" \ -+ "$$dir/$(GETTEXT_PACKAGE).mo"; \ -+ fi; \ -+ if test -r $$lang.gmo.m; then \ -+ $(INSTALL_DATA) $$lang.gmo.m $$dir/$(GETTEXT_PACKAGE).mo.m; \ -+ echo "installing $$lang.gmo.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \ -+ else \ -+ if test -r $(srcdir)/$$lang.gmo.m ; then \ -+ $(INSTALL_DATA) $(srcdir)/$$lang.gmo.m \ -+ $$dir/$(GETTEXT_PACKAGE).mo.m; \ -+ echo "installing $(srcdir)/$$lang.gmo.m as" \ -+ "$$dir/$(GETTEXT_PACKAGE).mo.m"; \ -+ else \ -+ true; \ -+ fi; \ -+ fi; \ -+ done -+ -+# Empty stubs to satisfy archaic automake needs -+dvi info ctags tags CTAGS TAGS ID: -+ -+# Define this as empty until I found a useful application. -+install-exec installcheck: -+ -+uninstall: -+ linguas="$(USE_LINGUAS)"; \ -+ for lang in $$linguas; do \ -+ rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \ -+ rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \ -+ done -+ -+check: all $(GETTEXT_PACKAGE).pot -+ rm -f missing notexist -+ srcdir=$(srcdir) $(INTLTOOL_UPDATE) -m -+ if [ -r missing -o -r notexist ]; then \ -+ exit 1; \ -+ fi -+ -+mostlyclean: -+ rm -f *.pox $(GETTEXT_PACKAGE).pot *.old.po cat-id-tbl.tmp -+ rm -f .intltool-merge-cache -+ -+clean: mostlyclean -+ -+distclean: clean -+ rm -f Makefile Makefile.in POTFILES stamp-it -+ rm -f *.mo *.msg *.cat *.cat.m *.gmo -+ -+maintainer-clean: distclean -+ @echo "This command is intended for maintainers to use;" -+ @echo "it deletes files that may require special tools to rebuild." -+ rm -f Makefile.in.in -+ -+distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) -+dist distdir: $(DISTFILES) -+ dists="$(DISTFILES)"; \ -+ extra_dists="$(EXTRA_DISTFILES)"; \ -+ for file in $$extra_dists; do \ -+ test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \ -+ done; \ -+ for file in $$dists; do \ -+ test -f $$file || file="$(srcdir)/$$file"; \ -+ ln $$file $(distdir) 2> /dev/null \ -+ || cp -p $$file $(distdir); \ -+ done -+ -+update-po: Makefile -+ $(MAKE) $(GETTEXT_PACKAGE).pot -+ tmpdir=`pwd`; \ -+ linguas="$(USE_LINGUAS)"; \ -+ for lang in $$linguas; do \ -+ echo "$$lang:"; \ -+ result="`$(MSGMERGE) -o $$tmpdir/$$lang.new.po $$lang`"; \ -+ if $$result; then \ -+ if cmp $(srcdir)/$$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ -+ rm -f $$tmpdir/$$lang.new.po; \ -+ else \ -+ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ -+ :; \ -+ else \ -+ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ -+ rm -f $$tmpdir/$$lang.new.po; \ -+ exit 1; \ -+ fi; \ -+ fi; \ -+ else \ -+ echo "msgmerge for $$lang.gmo failed!"; \ -+ rm -f $$tmpdir/$$lang.new.po; \ -+ fi; \ -+ done -+ -+Makefile POTFILES: stamp-it -+ @if test ! -f $@; then \ -+ rm -f stamp-it; \ -+ $(MAKE) stamp-it; \ -+ fi -+ -+stamp-it: Makefile.in.in $(top_builddir)/config.status POTFILES.in -+ cd $(top_builddir) \ -+ && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \ -+ $(SHELL) ./config.status -+ -+# Tell versions [3.59,3.63) of GNU make not to export all variables. -+# Otherwise a system limit (for SysV at least) may be exceeded. -+.NOEXPORT: --- accountsservice-0.6.37/debian/patches/2001-filtering_out_users.patch 2014-06-24 13:37:08.000000000 +1000 +++ accountsservice-0.6.40/debian/patches/2001-filtering_out_users.patch 1970-01-01 10:00:00.000000000 +1000 @@ -1,573 +0,0 @@ -From 330797e682d90776f5e8bb030533f94fe00b4245 Mon Sep 17 00:00:00 2001 -From: Ryan Lortie -Date: Wed, 26 Jun 2013 12:39:05 -0400 -Subject: [PATCH] Clean up user classification logic - -Bring back the simple login.defs-based check for if a user is human or -not and enable it by default. - -Add a build option --enable-user-heuristics to get the old behaviour -back again. - -Split out all human vs. system user divination into a new file, -user-classify.c in order to clean up daemon.c a bit. ---- - configure.ac | 6 ++ - src/Makefile.am | 2 + - src/daemon.c | 123 +------------------------- - src/daemon.h | 4 - - src/user-classify.c | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - src/user-classify.h | 32 +++++++ - src/user.c | 9 +- - 7 files changed, 293 insertions(+), 131 deletions(-) - create mode 100644 src/user-classify.c - create mode 100644 src/user-classify.h - -Index: accountsservice-0.6.34/configure.ac -=================================================================== ---- accountsservice-0.6.34.orig/configure.ac 2013-06-26 20:02:05.731804883 +0200 -+++ accountsservice-0.6.34/configure.ac 2013-06-26 20:02:05.715804882 +0200 -@@ -57,6 +57,12 @@ - ]) - 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])], -+ [if test "$enableval" = yes; then -+ AC_DEFINE([ENABLE_USER_HEURISTICS], , [System vs. human user heuristics enabled]) -+ fi]) -+ - dnl --------------------------------------------------------------------------- - dnl - Warnings - dnl --------------------------------------------------------------------------- -Index: accountsservice-0.6.34/src/Makefile.am -=================================================================== ---- accountsservice-0.6.34.orig/src/Makefile.am 2013-06-26 20:02:05.731804883 +0200 -+++ accountsservice-0.6.34/src/Makefile.am 2013-06-26 20:02:05.719804882 +0200 -@@ -42,6 +42,8 @@ - daemon.h \ - daemon.c \ - extensions.c \ -+ user-classify.h \ -+ user-classify.c \ - user.h \ - user.c \ - util.h \ -Index: accountsservice-0.6.34/src/daemon.c -=================================================================== ---- accountsservice-0.6.34.orig/src/daemon.c 2013-06-26 20:02:05.731804883 +0200 -+++ accountsservice-0.6.34/src/daemon.c 2013-06-26 20:02:05.719804882 +0200 -@@ -43,49 +43,17 @@ - #include - #include - -+#include "user-classify.h" - #include "daemon.h" - #include "util.h" - - #define PATH_PASSWD "/etc/passwd" - #define PATH_SHADOW "/etc/shadow" --#define PATH_NOLOGIN "/sbin/nologin" --#define PATH_FALSE "/bin/false" - #define PATH_GDM_CUSTOM "/etc/gdm/custom.conf" - #ifdef HAVE_UTMPX_H - #define PATH_WTMP _PATH_WTMPX - #endif - --static const char *default_excludes[] = { -- "bin", -- "root", -- "daemon", -- "adm", -- "lp", -- "sync", -- "shutdown", -- "halt", -- "mail", -- "news", -- "uucp", -- "operator", -- "nobody", -- "nobody4", -- "noaccess", -- "postgres", -- "pvm", -- "rpm", -- "nfsnobody", -- "pcap", -- "mysql", -- "ftp", -- "games", -- "man", -- "at", -- "gdm", -- "gnome-initial-setup", -- NULL --}; -- - enum { - PROP_0, - PROP_DAEMON_VERSION -@@ -96,7 +64,6 @@ - GDBusProxy *bus_proxy; - - GHashTable *users; -- GHashTable *exclusions; - - User *autologin; - -@@ -169,78 +136,6 @@ - return etype; - } - --gboolean --daemon_local_user_is_excluded (Daemon *daemon, -- const gchar *username, -- const gchar *shell, -- const gchar *password_hash) --{ -- int ret; -- -- if (g_hash_table_lookup (daemon->priv->exclusions, username)) { -- return TRUE; -- } -- -- ret = FALSE; -- -- if (shell != NULL) { -- char *basename, *nologin_basename, *false_basename; -- --#ifdef HAVE_GETUSERSHELL -- char *valid_shell; -- -- ret = TRUE; -- setusershell (); -- while ((valid_shell = getusershell ()) != NULL) { -- if (g_strcmp0 (shell, valid_shell) != 0) -- continue; -- ret = FALSE; -- } -- endusershell (); --#endif -- -- basename = g_path_get_basename (shell); -- nologin_basename = g_path_get_basename (PATH_NOLOGIN); -- false_basename = g_path_get_basename (PATH_FALSE); -- -- if (shell[0] == '\0') { -- ret = TRUE; -- } else if (g_strcmp0 (basename, nologin_basename) == 0) { -- ret = TRUE; -- } else if (g_strcmp0 (basename, false_basename) == 0) { -- ret = TRUE; -- } -- -- g_free (basename); -- g_free (nologin_basename); -- g_free (false_basename); -- } -- -- if (password_hash != NULL) { -- /* skip over the account-is-locked '!' prefix if present */ -- if (password_hash[0] == '!') -- password_hash++; -- -- if (password_hash[0] != '\0') { -- /* modern hashes start with "$n$" */ -- if (password_hash[0] == '$') { -- if (strlen (password_hash) < 4) -- ret = TRUE; -- -- /* DES crypt is base64 encoded [./A-Za-z0-9]* -- */ -- } else if (!g_ascii_isalnum (password_hash[0]) && -- password_hash[0] != '.' && -- password_hash[0] != '/') { -- ret = TRUE; -- } -- } -- -- } -- -- return ret; --} -- - #ifdef HAVE_UTMPX_H - - typedef struct { -@@ -520,7 +415,7 @@ - break; - - /* Skip system users... */ -- if (daemon_local_user_is_excluded (daemon, pwent->pw_name, pwent->pw_shell, NULL)) { -+ if (!user_classify_is_human (pwent->pw_uid, pwent->pw_name, pwent->pw_shell, NULL)) { - g_debug ("skipping user: %s", pwent->pw_name); - continue; - } -@@ -750,25 +645,13 @@ - static void - daemon_init (Daemon *daemon) - { -- gint i; - GFile *file; - GError *error; - - daemon->priv = DAEMON_GET_PRIVATE (daemon); - -- daemon->priv->exclusions = g_hash_table_new_full (g_str_hash, -- g_str_equal, -- g_free, -- NULL); -- - daemon->priv->extension_ifaces = daemon_read_extension_ifaces (); - -- for (i = 0; default_excludes[i] != NULL; i++) { -- g_hash_table_insert (daemon->priv->exclusions, -- g_strdup (default_excludes[i]), -- GUINT_TO_POINTER (TRUE)); -- } -- - daemon->priv->users = create_users_hash_table (); - - file = g_file_new_for_path (PATH_PASSWD); -@@ -1092,7 +975,7 @@ - uid = user_get_uid (user); - shell = user_get_shell (user); - -- if (daemon_local_user_is_excluded (data->daemon, name, shell, NULL)) { -+ if (!user_classify_is_human (uid, name, shell, NULL)) { - g_debug ("user %s %ld excluded", name, (long) uid); - continue; - } -Index: accountsservice-0.6.34/src/daemon.h -=================================================================== ---- accountsservice-0.6.34.orig/src/daemon.h 2013-06-26 20:02:05.731804883 +0200 -+++ accountsservice-0.6.34/src/daemon.h 2013-06-26 20:02:05.719804882 +0200 -@@ -77,10 +77,6 @@ - User *daemon_local_find_user_by_name (Daemon *daemon, - const gchar *name); - User *daemon_local_get_automatic_login_user (Daemon *daemon); --gboolean daemon_local_user_is_excluded (Daemon *daemon, -- const gchar *name, -- const gchar *shell, -- const gchar *password_hash); - - typedef void (*AuthorizedCallback) (Daemon *daemon, - User *user, -Index: accountsservice-0.6.34/src/user-classify.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ accountsservice-0.6.34/src/user-classify.c 2013-06-26 20:02:05.723804882 +0200 -@@ -0,0 +1,248 @@ -+/* -+ * Copyright (C) 2009-2010 Red Hat, Inc. -+ * Copyright (C) 2013 Canonical Limited -+ * -+ * 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 3 of the licence, 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 St, Fifth Floor, Boston, MA 02110-1301 USA -+ * -+ * Authors: Ryan Lortie -+ * Matthias Clasen -+ */ -+ -+#include "config.h" -+ -+#include "user-classify.h" -+ -+#include -+ -+#ifdef ENABLE_USER_HEURISTICS -+static const char *default_excludes[] = { -+ "bin", -+ "root", -+ "daemon", -+ "adm", -+ "lp", -+ "sync", -+ "shutdown", -+ "halt", -+ "mail", -+ "news", -+ "uucp", -+ "operator", -+ "nobody", -+ "nobody4", -+ "noaccess", -+ "postgres", -+ "pvm", -+ "rpm", -+ "nfsnobody", -+ "pcap", -+ "mysql", -+ "ftp", -+ "games", -+ "man", -+ "at", -+ "gdm", -+ "gnome-initial-setup" -+}; -+ -+#define PATH_NOLOGIN "/sbin/nologin" -+#define PATH_FALSE "/bin/false" -+ -+static gboolean -+user_classify_is_excluded_by_heuristics (const gchar *username, -+ const gchar *shell, -+ const gchar *password_hash) -+{ -+ static GHashTable *exclusions; -+ gboolean ret = FALSE; -+ -+ if (exclusions == NULL) { -+ guint i; -+ -+ exclusions = g_hash_table_new (g_str_hash, g_str_equal); -+ -+ for (i = 0; i < G_N_ELEMENTS (default_excludes); i++) { -+ g_hash_table_add (exclusions, (gpointer) default_excludes[i]); -+ } -+ } -+ -+ if (g_hash_table_contains (exclusions, username)) { -+ return TRUE; -+ } -+ -+ if (shell != NULL) { -+ char *basename, *nologin_basename, *false_basename; -+ -+#ifdef HAVE_GETUSERSHELL -+ char *valid_shell; -+ -+ ret = TRUE; -+ setusershell (); -+ while ((valid_shell = getusershell ()) != NULL) { -+ if (g_strcmp0 (shell, valid_shell) != 0) -+ continue; -+ ret = FALSE; -+ } -+ endusershell (); -+#endif -+ -+ basename = g_path_get_basename (shell); -+ nologin_basename = g_path_get_basename (PATH_NOLOGIN); -+ false_basename = g_path_get_basename (PATH_FALSE); -+ -+ if (shell[0] == '\0') { -+ ret = TRUE; -+ } else if (g_strcmp0 (basename, nologin_basename) == 0) { -+ ret = TRUE; -+ } else if (g_strcmp0 (basename, false_basename) == 0) { -+ ret = TRUE; -+ } -+ -+ g_free (basename); -+ g_free (nologin_basename); -+ g_free (false_basename); -+ } -+ -+ if (password_hash != NULL) { -+ /* skip over the account-is-locked '!' prefix if present */ -+ if (password_hash[0] == '!') -+ password_hash++; -+ -+ if (password_hash[0] != '\0') { -+ /* modern hashes start with "$n$" */ -+ if (password_hash[0] == '$') { -+ if (strlen (password_hash) < 4) -+ ret = TRUE; -+ -+ /* DES crypt is base64 encoded [./A-Za-z0-9]* -+ */ -+ } else if (!g_ascii_isalnum (password_hash[0]) && -+ password_hash[0] != '.' && -+ password_hash[0] != '/') { -+ ret = TRUE; -+ } -+ } -+ -+ } -+ -+ return ret; -+} -+ -+#else /* ENABLE_USER_HEURISTICS */ -+ -+static gboolean -+user_classify_parse_login_defs_field (const gchar *contents, -+ const gchar *key, -+ uid_t *result) -+{ -+ gsize key_len; -+ gint64 value; -+ gchar *end; -+ -+ key_len = strlen (key); -+ -+ for (;;) { -+ /* Our key has to be at the start of the line, followed by whitespace */ -+ if (strncmp (contents, key, key_len) == 0 && g_ascii_isspace (contents[key_len])) { -+ /* Found it. Move contents past the key itself and break out. */ -+ contents += key_len; -+ break; -+ } -+ -+ /* Didn't find it. Find the end of the line. */ -+ contents = strchr (contents, '\n'); -+ -+ /* EOF? */ -+ if (!contents) { -+ /* We didn't find the field... */ -+ return FALSE; -+ } -+ -+ /* Start at the beginning of the next line on next iteration. */ -+ contents++; -+ } -+ -+ /* 'contents' now points at the whitespace character just after -+ * the field name. strtoll can deal with that. -+ */ -+ value = g_ascii_strtoll (contents, &end, 10); -+ -+ if (*end && !g_ascii_isspace (*end)) { -+ g_warning ("Trailing junk after '%s' field in login.defs", key); -+ return FALSE; -+ } -+ -+ if (value <= 0 || value >= G_MAXINT32) { -+ g_warning ("Value for '%s' field out of range", key); -+ return FALSE; -+ } -+ -+ *result = value; -+ -+ return TRUE; -+} -+ -+static void -+user_classify_read_login_defs (uid_t *min_uid, -+ uid_t *max_uid) -+{ -+ GError *error = NULL; -+ char *contents; -+ -+ if (!g_file_get_contents ("/etc/login.defs", &contents, NULL, &error)) { -+ g_warning ("Could not open /etc/login.defs: %s. Falling back to default human uid range of %d to %d", -+ error->message, (int) *min_uid, (int) *max_uid); -+ g_error_free (error); -+ return; -+ } -+ -+ if (!user_classify_parse_login_defs_field (contents, "UID_MIN", min_uid)) { -+ g_warning ("Could not find UID_MIN value in login.defs. Using default of %d", (int) *min_uid); -+ } -+ -+ if (!user_classify_parse_login_defs_field (contents, "UID_MAX", max_uid)) { -+ g_warning ("Could not find UID_MIN value in login.defs. Using default of %d", (int) *max_uid); -+ } -+ -+ g_free (contents); -+} -+ -+static gboolean -+user_classify_is_in_human_range (uid_t uid) -+{ -+ static uid_t min_uid = 1000, max_uid = 60000; -+ static gboolean initialised; -+ -+ if (!initialised) { -+ user_classify_read_login_defs (&min_uid, &max_uid); -+ initialised = TRUE; -+ } -+ -+ return min_uid <= uid && uid <= max_uid; -+} -+#endif /* ENABLE_USER_HEURISTICS */ -+ -+gboolean -+user_classify_is_human (uid_t uid, -+ const gchar *username, -+ const gchar *shell, -+ const gchar *password_hash) -+{ -+#ifdef ENABLE_USER_HEURISTICS -+ return !user_classify_is_excluded_by_heuristics (username, shell, password_hash); -+#else -+ return user_classify_is_in_human_range (uid); -+#endif -+} -Index: accountsservice-0.6.34/src/user-classify.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ accountsservice-0.6.34/src/user-classify.h 2013-06-26 20:02:05.723804882 +0200 -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (C) 2013 Canonical Limited -+ * -+ * 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 3 of the licence, 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 St, Fifth Floor, Boston, MA 02110-1301 USA -+ * -+ * Author: Ryan Lortie -+ */ -+ -+#ifndef __USER_CLASSIFY_H__ -+#define __USER_CLASSIFY_H__ -+ -+#include -+#include -+ -+gboolean user_classify_is_human (uid_t uid, -+ const gchar *username, -+ const gchar *shell, -+ const gchar *password_hash); -+ -+#endif /* __USER_CLASSIFY_H__ */ -Index: accountsservice-0.6.34/src/user.c -=================================================================== ---- accountsservice-0.6.34.orig/src/user.c 2013-06-26 20:02:05.731804883 +0200 -+++ accountsservice-0.6.34/src/user.c 2013-06-26 20:02:05.727804883 +0200 -@@ -45,6 +45,7 @@ - #define GCR_API_SUBJECT_TO_CHANGE - #include - -+#include "user-classify.h" - #include "daemon.h" - #include "user.h" - #include "accounts-user-generated.h" -@@ -314,13 +315,7 @@ - g_object_notify (G_OBJECT (user), "password-mode"); - } - -- /* FIXME: this relies on heuristics that don't always come out -- * right. -- */ -- user->system_account = daemon_local_user_is_excluded (user->daemon, -- user->user_name, -- pwent->pw_shell, -- passwd); -+ user->system_account = !user_classify_is_human (user->uid, user->user_name, pwent->pw_shell, passwd); - - g_object_thaw_notify (G_OBJECT (user)); - --- accountsservice-0.6.37/debian/patches/git_custom_interfaces.patch 2014-06-24 13:37:08.000000000 +1000 +++ accountsservice-0.6.40/debian/patches/git_custom_interfaces.patch 1970-01-01 10:00:00.000000000 +1000 @@ -1,580 +0,0 @@ -From d83985af197ec3ee78cdd354838e00fc4c6892f8 Mon Sep 17 00:00:00 2001 -From: Ryan Lortie -Date: Wed, 17 Apr 2013 12:33:14 -0400 -Subject: [PATCH 2/3] service: add support for extension interfaces - -First pass at what a patch might look like. Requires the new GDBus -async property handling changes. - -https://bugs.freedesktop.org/show_bug.cgi?id=63733 ---- - src/Makefile.am | 1 + - src/daemon.c | 12 +++ - src/daemon.h | 3 + - src/extensions.c | 167 +++++++++++++++++++++++++++++++++ - src/user.c | 274 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 5 files changed, 457 insertions(+) - create mode 100644 src/extensions.c - -Index: accountsservice-0.6.34/src/Makefile.am -=================================================================== ---- accountsservice-0.6.34.orig/src/Makefile.am 2013-06-26 20:02:05.695804882 +0200 -+++ accountsservice-0.6.34/src/Makefile.am 2013-06-26 20:02:13.000000000 +0200 -@@ -41,6 +41,7 @@ - types.h \ - daemon.h \ - daemon.c \ -+ extensions.c \ - user.h \ - user.c \ - util.h \ -Index: accountsservice-0.6.34/src/daemon.c -=================================================================== ---- accountsservice-0.6.34.orig/src/daemon.c 2013-06-26 20:02:05.695804882 +0200 -+++ accountsservice-0.6.34/src/daemon.c 2013-06-26 20:02:13.000000000 +0200 -@@ -1,6 +1,7 @@ - /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2009-2010 Red Hat, Inc. -+ * Copyright (c) 2013 Canonical Limited - * - * 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 -@@ -110,6 +111,7 @@ - guint autologin_id; - - PolkitAuthority *authority; -+ GHashTable *extension_ifaces; - }; - - typedef struct passwd * (* EntryGeneratorFunc) (GHashTable *, gpointer *); -@@ -759,6 +761,8 @@ - g_free, - NULL); - -+ daemon->priv->extension_ifaces = daemon_read_extension_ifaces (); -+ - for (i = 0; default_excludes[i] != NULL; i++) { - g_hash_table_insert (daemon->priv->exclusions, - g_strdup (default_excludes[i]), -@@ -854,6 +858,8 @@ - - g_hash_table_destroy (daemon->priv->users); - -+ g_hash_table_unref (daemon->priv->extension_ifaces); -+ - G_OBJECT_CLASS (daemon_parent_class)->finalize (object); - } - -@@ -1792,6 +1798,12 @@ - return TRUE; - } - -+GHashTable * -+daemon_get_extension_ifaces (Daemon *daemon) -+{ -+ return daemon->priv->extension_ifaces; -+} -+ - static void - get_property (GObject *object, - guint prop_id, -Index: accountsservice-0.6.34/src/daemon.h -=================================================================== ---- accountsservice-0.6.34.orig/src/daemon.h 2013-06-26 20:02:05.695804882 +0200 -+++ accountsservice-0.6.34/src/daemon.h 2013-06-26 20:02:13.000000000 +0200 -@@ -101,6 +101,9 @@ - gboolean enabled, - GError **error); - -+GHashTable * daemon_read_extension_ifaces (void); -+GHashTable * daemon_get_extension_ifaces (Daemon *daemon); -+ - G_END_DECLS - - #endif /* __DAEMON_H__ */ -Index: accountsservice-0.6.34/src/extensions.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ accountsservice-0.6.34/src/extensions.c 2013-06-26 20:02:05.683804881 +0200 -@@ -0,0 +1,167 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- -+ * -+ * Copyright (c) 2013 Canonical Limited -+ * -+ * 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 3 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 St, Fifth Floor, Boston, MA 02110-1301 USA -+ * -+ * Written by: Ryan Lortie -+ */ -+ -+#include "config.h" -+ -+#include "daemon.h" -+ -+#include -+#include -+ -+static void -+daemon_maybe_add_extension_interface (GHashTable *ifaces, -+ GDBusInterfaceInfo *iface) -+{ -+ gint i; -+ -+ /* We visit the XDG data dirs in precedence order, so if we -+ * already have this one, we should not add it again. -+ */ -+ if (g_hash_table_contains (ifaces, iface->name)) -+ return; -+ -+ /* Only accept interfaces with only properties */ -+ if ((iface->methods && iface->methods[0]) || (iface->signals && iface->signals[0])) -+ return; -+ -+ /* Add it only if we can find the annotation */ -+ for (i = 0; iface->annotations && iface->annotations[i]; i++) { -+ if (g_str_equal (iface->annotations[i]->key, "org.freedesktop.Accounts.VendorExtension")) { -+ g_hash_table_insert (ifaces, g_strdup (iface->name), g_dbus_interface_info_ref (iface)); -+ return; -+ } -+ } -+} -+ -+static void -+daemon_read_extension_file (GHashTable *ifaces, -+ const gchar *filename) -+{ -+ GError *error = NULL; -+ GDBusNodeInfo *node; -+ gchar *contents; -+ gint i; -+ -+ if (!g_file_get_contents (filename, &contents, NULL, &error)) { -+ g_warning ("Unable to read extension file %s: %s. Ignoring.", filename, error->message); -+ g_error_free (error); -+ return; -+ } -+ -+ node = g_dbus_node_info_new_for_xml (contents, &error); -+ if (node) { -+ for (i = 0; node->interfaces && node->interfaces[i]; i++) -+ daemon_maybe_add_extension_interface (ifaces, node->interfaces[i]); -+ -+ g_dbus_node_info_unref (node); -+ } else { -+ g_warning ("Failed to parse file %s: %s", filename, error->message); -+ g_error_free (error); -+ } -+ -+ g_free (contents); -+} -+ -+static void -+daemon_read_extension_directory (GHashTable *ifaces, -+ const gchar *path) -+{ -+ const gchar *name; -+ GDir *dir; -+ -+ dir = g_dir_open (path, 0, NULL); -+ if (!dir) -+ return; -+ -+ while ((name = g_dir_read_name (dir))) { -+ gchar *filename; -+ gchar *symlink; -+ -+ /* Extensions are installed as normal D-Bus interface -+ * files with an annotation. -+ * -+ * D-Bus interface files are supposed to be installed in -+ * $(datadir)/dbus-1/interfaces/ but we don't want to -+ * scan all of the files there looking for interfaces -+ * that may contain our annotation. -+ * -+ * The solution is to install a symlink into a directory -+ * private to accountsservice and point it at the file, -+ * as installed in the usual D-Bus directory. -+ * -+ * This ensures compatibility with the future if we ever -+ * decide to check the interfaces directory directly -+ * (which might be a reasonable thing to do if we ever -+ * get an efficient cache of the contents of this -+ * directory). -+ * -+ * By introducing such a restrictive way of doing this -+ * now we ensure that everyone will do it in this -+ * forwards-compatible way. -+ */ -+ filename = g_build_filename (path, name, NULL); -+ symlink = g_file_read_link (filename, NULL); -+ -+ if (!symlink) { -+ g_warning ("Found accounts service vendor extension file %s, but file must be a symlink to " -+ "'../../dbus-1/interfaces/%s' for forwards-compatibility reasons.", filename, name); -+ g_free (filename); -+ continue; -+ } -+ -+ /* Ensure it looks like "../../dbus-1/interfaces/${name}" */ -+ const gchar * const prefix = "../../dbus-1/interfaces/"; -+ if (g_str_has_prefix (symlink, prefix) && g_str_equal (symlink + strlen (prefix), name)) { -+ daemon_read_extension_file (ifaces, filename); -+ } -+ else { -+ g_warning ("Found accounts service vendor extension symlink %s, but it must be exactly " -+ "equal to '../../dbus-1/interfaces/%s' for forwards-compatibility reasons.", -+ filename, name); -+ } -+ -+ g_free (filename); -+ g_free (symlink); -+ } -+ -+ g_dir_close (dir); -+} -+ -+GHashTable * -+daemon_read_extension_ifaces (void) -+{ -+ const gchar * const *data_dirs; -+ GHashTable *ifaces; -+ gint i; -+ -+ ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_dbus_interface_info_unref); -+ -+ data_dirs = g_get_system_data_dirs (); -+ for (i = 0; data_dirs[i]; i++) { -+ gchar *path = g_build_filename (data_dirs[i], "accountsservice/interfaces", NULL); -+ -+ daemon_read_extension_directory (ifaces, path); -+ -+ g_free (path); -+ } -+ -+ return ifaces; -+} -Index: accountsservice-0.6.34/src/user.c -=================================================================== ---- accountsservice-0.6.34.orig/src/user.c 2013-06-26 20:02:05.695804882 +0200 -+++ accountsservice-0.6.34/src/user.c 2013-06-26 20:02:13.000000000 +0200 -@@ -3,6 +3,7 @@ - * Copyright (C) 2004-2005 James M. Cape . - * Copyright (C) 2007-2008 William Jon McCann - * Copyright (C) 2009-2010 Red Hat, Inc. -+ * Copyright © 2013 Canonical Limited - * - * 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 -@@ -115,6 +116,9 @@ - gboolean automatic_login; - gboolean system_account; - gboolean local_account; -+ -+ guint *extension_ids; -+ guint n_extension_ids; - }; - - typedef struct UserClass -@@ -511,6 +515,259 @@ - 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) - { -@@ -548,6 +805,8 @@ - } - return; - } -+ -+ user_register_extensions (user); - } - - void -@@ -560,6 +819,21 @@ - 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 --- accountsservice-0.6.37/debian/patches/git_hold_keyfiles.patch 2014-06-24 13:37:08.000000000 +1000 +++ accountsservice-0.6.40/debian/patches/git_hold_keyfiles.patch 1970-01-01 10:00:00.000000000 +1000 @@ -1,116 +0,0 @@ -From 456eeb47ee9874693d18df121eecd2d16187bd06 Mon Sep 17 00:00:00 2001 -From: Ryan Lortie -Date: Wed, 17 Apr 2013 08:48:12 +0200 -Subject: [PATCH 1/3] User: hold on to our keyfile - -When updating a User object from keyfile, keep reference on the keyfile -object passed in and modify the Daemon not to destroy it. - -When saving a User, instead of creating a new keyfile, reuse the one we -stored on the object. - -We still record the properties from the User object into the keyfile in -the previous way (and include a modification to clear out the 'User' -group before doing this). - -The intention here is to allow other groups stored in the keyfile to be -preserved. These other groups are likely to correspond to extension -interfaces (which will be introduced in future patches). - -An alternative approach would have been to only preserve groups for -extensions that we currently have loaded but this was abandoned as being -excessively brittle since the result of a temporarily missing extension -file would be the destruction of data. - -https://bugs.freedesktop.org/show_bug.cgi?id=63733 ---- - src/daemon.c | 2 +- - src/user.c | 17 ++++++++++++----- - 2 files changed, 13 insertions(+), 6 deletions(-) - -Index: accountsservice-0.6.34/src/daemon.c -=================================================================== ---- accountsservice-0.6.34.orig/src/daemon.c 2013-06-26 20:02:05.659804880 +0200 -+++ accountsservice-0.6.34/src/daemon.c 2013-06-26 20:02:14.000000000 +0200 -@@ -493,7 +493,7 @@ - key_file = g_key_file_new (); - if (g_key_file_load_from_file (key_file, filename, 0, NULL)) - user_update_from_keyfile (user, key_file); -- g_key_file_free (key_file); -+ g_key_file_unref (key_file); - g_free (filename); - } - -Index: accountsservice-0.6.34/src/user.c -=================================================================== ---- accountsservice-0.6.34.orig/src/user.c 2013-06-26 20:02:05.659804880 +0200 -+++ accountsservice-0.6.34/src/user.c 2013-06-26 20:02:14.000000000 +0200 -@@ -87,6 +87,8 @@ - - GHashTable *secret_exchanges; - -+ GKeyFile *keyfile; -+ - uid_t uid; - gid_t gid; - gchar *user_name; -@@ -404,6 +406,9 @@ - } - } - -+ g_clear_pointer (&user->keyfile, g_key_file_unref); -+ user->keyfile = g_key_file_ref (keyfile); -+ - g_object_thaw_notify (G_OBJECT (user)); - } - -@@ -431,6 +436,8 @@ - user_save_to_keyfile (User *user, - GKeyFile *keyfile) - { -+ g_key_file_remove_group (keyfile, "User", NULL); -+ - if (user->email) - g_key_file_set_string (keyfile, "User", "Email", user->email); - -@@ -465,15 +472,13 @@ - save_extra_data (User *user) - { - gchar *filename; -- GKeyFile *keyfile; - gchar *data; - GError *error; - -- keyfile = g_key_file_new (); -- user_save_to_keyfile (user, keyfile); -+ user_save_to_keyfile (user, user->keyfile); - - error = NULL; -- data = g_key_file_to_data (keyfile, NULL, &error); -+ data = g_key_file_to_data (user->keyfile, NULL, &error); - if (error == NULL) { - filename = g_build_filename (USERDIR, - user->user_name, -@@ -486,7 +491,6 @@ - user->user_name, error->message); - g_error_free (error); - } -- g_key_file_free (keyfile); - } - - static void -@@ -2708,6 +2712,8 @@ - - g_hash_table_unref (user->secret_exchanges); - -+ g_clear_pointer (&user->keyfile, g_key_file_unref); -+ - g_free (user->object_path); - g_free (user->user_name); - g_free (user->real_name); -@@ -2961,4 +2967,5 @@ - user->automatic_login = FALSE; - user->system_account = FALSE; - user->login_history = NULL; -+ user->keyfile = g_key_file_new (); - } --- accountsservice-0.6.37/debian/patches/series 2014-07-31 01:23:19.000000000 +1000 +++ accountsservice-0.6.40/debian/patches/series 2015-01-25 13:38:03.000000000 +1100 @@ -15,4 +15,3 @@ 0002-On-startup-clean-out-the-data-of-removed-users.patch 0020-support-login.defs.patch 0021-support-extrausers.patch -0022-fix-desktop-centric-polkit-policy.patch