debian/0000775000000000000000000000000012266271062007174 5ustar debian/libaccountsservice-doc.links0000664000000000000000000000012412240704573014665 0ustar usr/share/doc/libaccountsservice-doc/html usr/share/gtk-doc/html/libaccountsservice debian/copyright0000664000000000000000000000422212240704573011127 0ustar Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: AccountsService Upstream-Contact: Matthias Clasen Source: http://cgit.freedesktop.org/accountsservice/ Files: * Copyright: 2009-2010 Red Hat, Inc License: GPL-3+ Files: src/user.c src/libaccountsservice/act-user.* src/libaccountsservice/act-user.manager.* doc/dbus/spec-to-docbook.xsl Copyright: 2009-2010 Red Hat, Inc 2007-2008 William Jon McCann 2004-2005 James M. Cape License: GPL-2+ Files: debian/* Copyright: 2011 Alessio Treglia License: GPL-3+ License: GPL-3+ 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. Comment: On Debian systems the full text of the GNU General Public License can be found in the `/usr/share/common-licenses/GPL-3' file. . You should have received a copy of the GNU General Public License along with this program. If not, see . License: GPL-2+ 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. Comment: On Debian systems the full text of the GNU General Public License can be found in the `/usr/share/common-licenses/GPL-2' file. . You should have received a copy of the GNU General Public License along with this program. If not, see . debian/changelog0000664000000000000000000006400712266271050011052 0ustar accountsservice (0.6.35-0ubuntu7) trusty; urgency=medium * debian/patches/0007-add-lightdm-support.patch: - updated to not keep polling on an inexistant gdm (or lightdm) configurations, fixed the code checking if gdm is running as well (thanks Lars for hints on how to do that one correctly) (lp: #1234289) -- Sebastien Bacher Fri, 17 Jan 2014 18:09:20 +0100 accountsservice (0.6.35-0ubuntu6) trusty; urgency=low [ Tim Lunn ] * debian/gir1.2-accountsservice-1.0.install: Don't install typelib file to multiarch path (LP: #1260880) [ Rico Tzschichholz ] * Don't multiarch gir1.2-accountsservice-1.0 (LP: #1260604) * Add gir1.2-accountsservice-1.0 to libaccountsservice-dev depends. -- Tim Lunn Sat, 14 Dec 2013 09:38:23 +1100 accountsservice (0.6.35-0ubuntu5) trusty; urgency=low * debian/patches/0017-clean-up-cache-dir.patch: Remove only if errno is zero, and then remove the icon as well. -- Gunnar Hjalmarsson Thu, 12 Dec 2013 23:09:00 +0100 accountsservice (0.6.35-0ubuntu4) trusty; urgency=low * Remove pointless dependency on libgirepository1.0-dev. -- Dimitri John Ledkov Thu, 12 Dec 2013 17:10:10 +0000 accountsservice (0.6.35-0ubuntu3) trusty; urgency=low * Bump debian/compat to 9. * Convert to multiarch (LP: #1260370). -- Dimitri John Ledkov Thu, 12 Dec 2013 16:07:54 +0000 accountsservice (0.6.35-0ubuntu2) trusty; urgency=low [ Robert Ancell ] * debian/patches/0017-clean-up-cache-dir.patch: Remove user cache files if user account no longer exists (LP: #1259562). -- Gunnar Hjalmarsson Wed, 11 Dec 2013 14:22:00 +0100 accountsservice (0.6.35-0ubuntu1) trusty; urgency=low * New upstream version * Refreshed the patches * debian/control: - don't build-depends on valac - updated glib requirement * debian/libaccountsservice-dev.install: - don't install the vapi, upstream dropped it * debian/patches/git_hold_keyfiles.patch, debian/patches/git_custom_interfaces.patch, debian/patches/2001-filtering_out_users.patch: - dropped, the changes are in the new version -- Sebastien Bacher Wed, 13 Nov 2013 15:15:40 +0100 accountsservice (0.6.34-0ubuntu7) trusty; urgency=low * debian/patches/0009-language-tools.patch: Don't try to maintain a LANGUAGE priority list if language-selector-gnome is not present (LP: #1240058). -- Gunnar Hjalmarsson Sun, 03 Nov 2013 23:38:00 +0100 accountsservice (0.6.34-0ubuntu6) saucy; urgency=low * Fix various memory leaks. References: - https://bugzilla.redhat.com/show_bug.cgi?id=1000364 - http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=723745 -- Alessio Treglia Sat, 21 Sep 2013 23:24:14 +0100 accountsservice (0.6.34-0ubuntu5) saucy; urgency=low * debian/patches/0016-add-input-sources-support.patch: - Store input sources in the user object. -- William Hua Wed, 31 Jul 2013 12:44:00 -0400 accountsservice (0.6.34-0ubuntu4) saucy; urgency=low * Move gtk-doc-tools to Build-Depends from Build-Depends-Indep. -- Adam Conrad Mon, 29 Jul 2013 16:13:05 +0100 accountsservice (0.6.34-0ubuntu3) saucy; urgency=low * Merge some changes from Debian: - Bump build-deps on glib-2.0 >= 2.34. - Add gtk-doc-tools to Build-Depends-Indep. - Build libaccountsservice's documentation - Bump Standards - Fix VCS canonical URLs. - Refresh some patches * Don't build-depend on gnome-doc-utils -- Jeremy Bicha Sat, 27 Jul 2013 23:18:48 -0400 accountsservice (0.6.34-0ubuntu2) saucy; urgency=low * debian/patches/0015-pam-pin-ubuntu.patch: - Split Ubuntu integration changes to 0014-pam-pin.patch out into a a separate patch to make it easier to update 0014 from the upstream bug as needed. - Fix setting password via DBus (LP: #1195021) -- Michael Terry Wed, 03 Jul 2013 15:06:53 -0400 accountsservice (0.6.34-0ubuntu1) saucy; urgency=low * New upstream version * Refreshed patches * debian/libaccountsservice0.symbols: - updated for the new version (and some of the previous ones) * debian/patches/0014-pam-pin.patch: - updated to fix a double free issue * debian/patches/git_custom_interfaces.patch, debian/patches/git_hold_keyfiles.patch: - support for adding custom settings, thanks Ryan Lortie * debian/patches/2001-filtering_out_users.patch: - updated with a patch proposed upstream, thanks Ryan -- Sebastien Bacher Wed, 26 Jun 2013 15:42:50 +0200 accountsservice (0.6.29-1ubuntu10) saucy; urgency=low * debian/patches/0014-pam-pin.patch: - Add experimental PAM module for PIN codes. Patch mostly by Giovanni Campagna from upstream bug. Ideally will be useful for phablets that want to show a PIN unlock screen. -- Michael Terry Mon, 06 May 2013 21:17:43 -0400 accountsservice (0.6.29-1ubuntu9) saucy; urgency=low * Add git_logind_check.patch: Check for logind, not for systemd. * Switch from ConsoleKit to to logind. -- Martin Pitt Mon, 29 Apr 2013 11:24:49 -0700 accountsservice (0.6.29-1ubuntu8) raring; urgency=low * debian/patches/0009-language-tools.patch: Take /usr/local/share/locale into account when generating the list of language options (LP: #1159496). -- Gunnar Hjalmarsson Fri, 29 Mar 2013 06:19:34 +0100 accountsservice (0.6.29-1ubuntu7) raring; urgency=low * debian/patches/0009-language-tools.patch: - Code for migration from ~/.profile to ~/.pam_environment dropped. This was done in 12.04 LTS already. * debian/patches/0010-set-language.patch: - Code for parsing /etc/default/locale made able to deal with both quoted and non-quoted entries (LP: #1159290). - Code for migration from ~/.profile to ~/.pam_environment dropped. This was done in 12.04 LTS already. - A couple of memory leaks fixed. -- Gunnar Hjalmarsson Sun, 24 Mar 2013 20:33:00 +0100 accountsservice (0.6.29-1ubuntu6) raring; urgency=low * debian/patches/0009-language-tools.patch: Set the PAPERSIZE env. variable in ~/.pam_environment, since LC_PAPER is ignored by many apps (LP: #1130690). -- Gunnar Hjalmarsson Thu, 21 Feb 2013 23:53:00 +0100 accountsservice (0.6.29-1ubuntu5) raring; urgency=low * debian/patches/0009-language-tools.patch: Prevent language-options from listing items that don't correspond with an installed langpack, even if there is a matching locale (LP: #960314). -- Gunnar Hjalmarsson Wed, 30 Jan 2013 02:10:00 +0100 accountsservice (0.6.29-1ubuntu4) raring; urgency=low * debian/patches/0010-set-language.patch: Run user_HOME_available() as user in order to prevent incorrect failures when HOME is on NFS (LP: #1083605). -- Gunnar Hjalmarsson Wed, 23 Jan 2013 08:19:27 -0500 accountsservice (0.6.29-1ubuntu3) raring; urgency=low [ Albert Astals Cid ] * debian/patches/0007-add-lightdm-support.patch: - Fix reporting of autologin setting for users when using lightdm (LP: #1043349) -- Michael Terry Tue, 22 Jan 2013 14:11:08 -0500 accountsservice (0.6.29-1ubuntu2) raring; urgency=low * debian/control: build-depends on valac -- Sebastien Bacher Thu, 29 Nov 2012 21:49:16 +0100 accountsservice (0.6.29-1ubuntu1) raring; urgency=low * Resync on Debian, remaining diffs: * debian/accountsservice.postinst: - don't try restarting the service from the maintainer script after upgrades, it leads to some issues and shouldn't be needed since it will be dbus reactivated when needed (lp: #1021293) * debian/libaccountsservice-dev.install: - install vala directory * debian/patches/0001-formats-locale-property.patch: - readded bit of the patch that seems to not be in the debian version * debian/patches/0002-create-and-manage-groups-like-on-a-ubuntu-system.patch: - updated to gdbus * debian/patches/0005-gdm_config_file_path.patch - drop patch since it breaks setting automatic login. (LP: #1059090) * debian/patches/0007-add-lightdm-support.patch: - used Ubuntu version, they are slightly different * debian/patches/0008-nopasswdlogin-group.patch: - used Ubuntu version, they are slightly different * debian/patches/0009-language-tools.patch: - used Ubuntu version, they are slightly different * debian/patches/0010-set-language.patch: - used Ubuntu version, they are slightly different * debian/patches/0011-add-background-file-support.patch: - updated for the gdbus codebase * debian/patches/0012-add-keyboard-layout-support.patch: - updated for the gdbus codebase * debian/patches/0013-add-has-message-support.patch: - updated for the gdbus codebase * debian/patches/git_correct_32bit_type.patch: - backport upstream fix for a 32bit segfault issue -- Sebastien Bacher Thu, 19 Jul 2012 19:00:43 +0200 accountsservice (0.6.29-1) experimental; urgency=low * New upstream release: - Changes since 0.6.25: + Uninitialized variable fix + Typo fix + Create data dirs just-in-time + Ignore closing sessions for is_logged_in test + Disable NULL user for delete_user call + Translation updates - Changes since 0.6.26: + Require libsystemd-login 186 + Protect against deleting root user + Add LoginTime and LoginHistory properties + fix crash consolekit code + fix has_multiple_user property after removing user - Changes since 0.6.27: + Fix warnings when the singleton user manager object is finalized + Generated docs for libaccountsservice + Initialize local_acount to TRUE + Add async api for user creation, caching and deletion - Changes since 0.6.28: + Fix act_user_manager_delete_user_finish + Fix handling of LoginTime and LoginHistory properties - Changes since 0.6.29: + Translate D-Bus errors to local errors in libaccountsservice + Fix a wrong property name n the login history support * Refresh patches. * Update symbols control file. * Don't build gtk-docs for now. -- Alessio Treglia Thu, 11 Oct 2012 16:10:45 +0100 accountsservice (0.6.24-1) experimental; urgency=low * New upstream release: - add User.Local property for identifying local users - Fix up some debug output - add new CacheUser and UncacheUser apis - uncache user before deleting user - Correct CVE-2012-2737, local file disclosure - small memory leak fix - exclude system accounts from ListCachedUsers - make has-multiple-users properly only check non-system users - remove icon when deleting user - Revert usage of getpwent() as fallback for fgetpwent - support consolekit call cancellation to prevent crashes caused by shortlived sessions * Refresh patches, removed those applied upstream: - 9001-manage_pending_ck_calls_with_cancellable.patch - 9002-memory_leak_actuser.c - 9003-CVE-2012-2737.patch * Refresh symbols file. -- Alessio Treglia Fri, 07 Sep 2012 18:53:51 +0200 accountsservice (0.6.21-6) unstable; urgency=high * CVE-2012-2737: Add patch to prevent race condition with UID lookup (Closes: #679429): - src/u{ser,til}.c: Use bus daemon to query peer credentials. -- Alessio Treglia Tue, 10 Jul 2012 17:04:54 +0200 accountsservice (0.6.21-5) unstable; urgency=medium * Add patch grabbed from upstream git to fix memory leaks in src/libaccountsservice/act-user.c. Set urgency to medium since the package has already migrated to testing. -- Alessio Treglia Sat, 23 Jun 2012 12:46:22 +0200 accountsservice (0.6.21-4) unstable; urgency=low * Manage pending consolekit calls with GtkCancellable to fix SIGSEGV in libaccountsservice. (Closes: #673185) -- Alessio Treglia Wed, 13 Jun 2012 09:02:33 +0200 accountsservice (0.6.21-3) unstable; urgency=low * Strip SystemdService out of org.freedesktop.Accounts.service service file. (Closes: #675925) -- Alessio Treglia Thu, 07 Jun 2012 15:09:19 +0200 accountsservice (0.6.21-2) unstable; urgency=low * Disable systemd support: - Let accountsservice build on non-Linux (Closes: #674433) - Attempt to solve #673185 -- Alessio Treglia Sat, 02 Jun 2012 22:59:49 +0200 accountsservice (0.6.21-1) unstable; urgency=low * New upstream release. * Refresh patches. * Add libaccountsservice-dbg package. -- Alessio Treglia Fri, 18 May 2012 17:23:55 +0200 accountsservice (0.6.18-3) unstable; urgency=low * Revert upstream commit 552a0c856a6e3a7c2e6450ab80e79f4204062281 and then fix a regression introduced since 0.6.16: - Filter out users which have UIDs lower than UID_MIN specified in etc/login.defs instead of checking if they have /usr/sbin/nologin as login shell. (Closes: #673095) Thanks to Michael Biebl for the report. -- Alessio Treglia Wed, 16 May 2012 09:52:58 +0200 accountsservice (0.6.18-2) unstable; urgency=low * Upload to unstable. -- Alessio Treglia Tue, 15 May 2012 07:48:08 +0200 accountsservice (0.6.18-1) experimental; urgency=low * Upload to experimental due to the big amount of changes. * Imported Upstream version 0.6.18: - Fix systemd configure check - Add a few more common system accounts to the blacklist - Fix some issues in systemd session handling * Imported Upstream version 0.6.17: - Fix user filtering which was broken in 0.6.16. - Fix double free in user code. * Imported Upstream version 0.6.16: - Don't filter out users below UID_MIN in login.defs - Filter out users with invalid shells - build fixes for srcdir != builddir - Port to GDBus - Add systemd support - vala support and introspection fixes - ppc32 fixes - use infinite timeout for ListCachedUsers calls - Translation updates * Migrate 0007-add-lightdm-support.patch to GDBus: - More testing would be appreciated. * Remove 2001-icon_reset.patch, applied upstream. * Remove 3001-show_more_than_one_user_powerpc.patch, applied upstream. * Remove obsolete patches: - 0003-getpwnam_null_crash.patch - 0004-history-filter-sessions.patch * Refresh systemd's build-deps. * Drop {,build-}dependency on libdbus-glib-1-dev. * Refresh symbols. * Refresh debian/copyright. * Update debian/watch. * Bump Standards. -- Alessio Treglia Mon, 30 Apr 2012 13:19:46 +0200 accountsservice (0.6.15-4) unstable; urgency=low * src/user.c: Be more careful when resetting the users icons - When the current icon is in /usr/share, and we reset the icon, we try to delete a nonexisting icon file in /var/lib/AccountsService/icons. Deal with this eventuality. * fix compute_object_path on powerpc (Closes: #635168) - long isn't necessarily 64bit. On big endian architectures, where it's smaller than 64bit, the compute_object_path function will get computed incorrectly; thanks to Ray Strode and Michel Dänzer. * Apply 2001-icon_reset.patch,3001-show_more_than_one_user_powerpc.patch on Ubuntu too. * Integrate Ubuntu patches and apply them in debian/patches/ubuntu.series (for Ubuntu only): - 0001-formats-locale-property.patch - 0002-create-and-manage-groups-like-on-a-ubuntu-system.patch - 0005-gdm_config_file_path_ubuntu.patch - 0008-nopasswdlogin-group.patch - 0009-language-tools.patch - 0010-set-language.patch - 0011-add-background-file-support.patch - 0012-add-keyboard-layout-support.patch - 0013-add-has-message-support.patch -- Alessio Treglia Sun, 19 Feb 2012 00:37:07 +0100 accountsservice (0.6.15-3) unstable; urgency=low * Move GIR package into the new section "introspection". * debian/patches/0011-add-background-file-support.patch - Add support for a BackgroundFile property, similar to IconFile. Apply on Ubuntu only. (LP: #844081) * Fix file permissions bypass (LP: #904395), applies on Ubuntu only: - debian/patches/0010-set-language.patch: Drop privileges before letting help scripts in /usr/share/language-tools write to $HOME. - debian/patches/0009-language-tools.patch: Drop chown() call in /usr/share/language-tools/save-to-profile. CVE-2011-4406 * Refresh patches. -- Alessio Treglia Tue, 31 Jan 2012 17:41:50 +0100 accountsservice (0.6.15-2) unstable; urgency=low [ Gunnar Hjalmarsson ] * 0009-language-tools.patch: Sort the list of language options, for the language chooser in LightDM (LP: #868346). [ Martin Pitt ] * 0002-create-and-manage-groups-like-on-a-ubuntu-system.patch: Use "sudo" group instead of "admin", for Debian/sudo compatibility. However, keep recognizing "admin" as administrator, too. (LP: #893842) -- Martin Pitt Fri, 25 Nov 2011 08:28:18 +0100 accountsservice (0.6.15-1) unstable; urgency=low [ Alessio Treglia ] * New upstream release: - fix build on FreeBSD and OpenBSD - only accept regular files as icons - don't track non-graphical sessions - fix wtmp handling * Refresh Debian's patches. * Refresh Ubuntu's patches. * Update debian/copyright to comply with DEP-4 rev-174. [ Martin Pitt ] * 0002-create-and-manage-groups-like-on-a-ubuntu-system.patch: Add admin users to the same groups as Ubiquity, i. e. add "adm", "lpadmin", and "sambashare". Patch by Rodrigo Moya. (LP #810907) * Add 0007-add-lightdm-support.patch: Support setting/reading LightDM autologin settings. Patch by Mike Terry. Applied to both Debian and Ubuntu builds. (fd.o #40020, LP#798962) * Add 0008-nopasswdlogin-group.patch: When setting a user to have no password, also add them to the 'nopasswdlogin' group. Patch by Mike Terry. (Applied for Ubuntu only.) (LP #815271) * Add 0009-language-tools.patch: Helper scripts for managing the language environment are made available in /usr/share/language-tools. They are supporting accountsservice's "SetLanguage" method, but for now some of the files may also be called from other packages directly. Patch by Gunnar Hjalmarsson. (Applied for Ubuntu only.) * Add 0010-set-language.patch: When a new language is set, update the user's ~/.profile file with the corresponding environment variables. Patch by Gunnar Hjalmarsson. (Applied for Ubuntu only.) * debian/rules: Install language tools, when built. * 0002-create-and-manage-groups-like-on-a-ubuntu-system.patch: - Add admin users to the same groups as Ubiquity, i. e. add "adm", "lpadmin", and "sambashare". Patch by Rodrigo Moya. (LP #810907) * Add 0008-nopasswdlogin-group.patch: When setting a user to have no password, also add them to the 'nopasswdlogin' group. Patch by Mike Terry. (Applied for Ubuntu only.) (LP #815271) * Add Ubuntu patches for writing "SetLanguage" values to ~/.profile. * Add 0007-add-lightdm-support.patch: Support setting/reading LightDM autologin settings. Patch by Mike Terry. Applied to both Debian and Ubuntu builds. (fd.o #40020, LP#798962) -- Alessio Treglia Tue, 18 Oct 2011 21:50:35 +0200 accountsservice (0.6.14-1) unstable; urgency=low * New upstream release: - ignore extraneous SetAutomaticLogin(false) calls for a user - monitor /etc/gdm/custom.conf for changes in autologin config - fix fast user switching - fix docs to build - translation updates * Refresh Debian's series of patches. * Refresh Ubuntu's series of patches. -- Alessio Treglia Mon, 05 Sep 2011 23:55:45 +0200 accountsservice (0.6.13-1) unstable; urgency=low * New upstream release: - honor aclocal flags environment variable - set log domain so it can be hushed - use wtmp instead of consolekit for determining login frequency + Use the POSIX wtmpx database instead of ConsoleKit as source for calculating login frequency. This is more portable and much simpler. Also, it allows us to prepare accountsservice for the post-CK times. (upstream bug: https://bugs.freedesktop.org/39295) - leak and warning fixes - clean up polkit deprectation warnings - add '--' before username to account helper programs * Dropped patches (they don't apply for now): - 0001-do-not-consider-system-users-returned-from-consolekit.patch - 0003-getpwnam_null_crash.patch - 0004-history-filter-sessions.patch * Refreshed: - 0002-create-and-manage-groups-like-on-a-{debian,ubuntu}-system.patch - 0005-gdm_config_file_path.patch * Update symbols. * debian/patches/0006-adduser_instead_of_useradd.patch - Replace useradd with adduser to comply with Debian Policy. In collaboration with Ubuntu, thanks to Sebastien Bacher and other Ubuntu guys (LP: #810907). * Remove the dummy package gir1.2-accountservice-1.0, the previous version has already reached Wheezy and there is no reverse dependencies. -- Alessio Treglia Mon, 25 Jul 2011 12:17:33 +0200 accountsservice (0.6.12-5) unstable; urgency=low [ Martin Pitt ] * debian/control: Add missing Breaks/Replaces: to gir1.2-accountsservice-1.0 for the package renaming. -- Alessio Treglia Sat, 09 Jul 2011 09:18:25 +0200 accountsservice (0.6.12-4) unstable; urgency=low * Fix mistake in the name of a runtime package: - Rename gir1.2-accountservice-1.0 to gir1.2-accountsservice-1.0. - Introduce a transitional dummy package for a tiny-and-smooth transition. * Enable parallel building. -- Alessio Treglia Thu, 30 Jun 2011 10:38:40 +0200 accountsservice (0.6.12-3) unstable; urgency=low * Add accountsservice.{postinst,prerm} scripts to properly shut down the daemon on package upgrade and removal (Closes: #630577); thanks to Rodrigo Moya for the patch. -- Alessio Treglia Thu, 16 Jun 2011 11:09:34 +0200 accountsservice (0.6.12-2) unstable; urgency=low * Disable 0005-gdm_config_file_path.patch in debian/patches/ubuntu.series as it doesn't apply to Ubuntu. * On Ubuntu apply 0002-create-and-manage-groups-like-on-a-ubuntu-system.patch instead of 0002-create-and-manage-groups-like-on-a-debian-system.patch -- Alessio Treglia Sun, 05 Jun 2011 12:40:37 +0200 accountsservice (0.6.12-1) unstable; urgency=low * New upstream bugfix release. * Update symbols. * Fix path to the GDM configuration file, which is different in Debian (Closes: #627311). * Refresh patches. -- Alessio Treglia Sun, 22 May 2011 10:21:10 +0200 accountsservice (0.6.10-1) unstable; urgency=low * New upstream release: - An assortment of race fixes. - Translation updates. -- Alessio Treglia Sat, 07 May 2011 13:02:07 +0200 accountsservice (0.6.9-2) unstable; urgency=low * Small change to reload_ck_history in order to make accountsservice filter by 'x11' session type (Closes: #624474); thanks to Josselin Mouette for the report and patch. * Bump Standards. -- Alessio Treglia Thu, 28 Apr 2011 20:03:07 +0200 accountsservice (0.6.9-1) unstable; urgency=low * New upstream release. * Refresh patches. * Update symbols file. -- Alessio Treglia Tue, 26 Apr 2011 08:20:11 +0200 accountsservice (0.6.8-2) unstable; urgency=low * Upload to unstable. * Add patch to prevent crash due to getpwnam returning a NULL pointer. Thanks to Mattias Eriksson for the patch. * Add symbols file. -- Alessio Treglia Thu, 14 Apr 2011 11:01:37 +0200 accountsservice (0.6.8-1) experimental; urgency=low * Imported Upstream version 0.6.8. * Refresh patches. -- Alessio Treglia Fri, 08 Apr 2011 09:51:48 +0200 accountsservice (0.6.6-4) experimental; urgency=low [ Josselin Mouette ] * 0002-create-and-manage-groups-like-on-a-debian-system.patch: - fixed to not add user to useless group, and to use sudo instead of admin (Closes: #619914). -- Alessio Treglia Tue, 29 Mar 2011 11:44:39 +0200 accountsservice (0.6.6-3) experimental; urgency=low * Pass systemd unit dir to the configure script to properly provide service file (Closes: #619796); thanks to Alban Browaeys for the report. -- Alessio Treglia Sun, 27 Mar 2011 10:11:39 +0200 accountsservice (0.6.6-2) experimental; urgency=low * Rename 0001-buildsystem.patch -> 1001-buildsystem.patch * Match Debian user/groups system; thanks to Frederic Peters for the patchset (Closes: #618764): - 0001-do-not-consider-system-users-returned-from-consolekit.patch. - 0002-create-and-manage-groups-like-on-a-debian-system.patch. -- Alessio Treglia Sat, 19 Mar 2011 10:39:28 +0100 accountsservice (0.6.6-1) experimental; urgency=low * New upstream release. -- Alessio Treglia Fri, 18 Mar 2011 10:28:02 +0100 accountsservice (0.6.5-2) experimental; urgency=low * Switch libaccountsservice-dev to architecture 'any'; also closes: #618643. -- Alessio Treglia Thu, 17 Mar 2011 11:20:19 +0100 accountsservice (0.6.5-1) experimental; urgency=low * New upstream release. * Update build-dependencies. * Switch to dh-autoreconf. * Provide po/Makefile.in.in * Don't build static libraries * Split files in several packages: - accountsservice to provide the runtime service files. - libaccountsservice0 to provide the shared libraries. - libaccountsservice-dev to provide the development files. - gir1.0-accountservice-1.0 to provide GObject introspection data files. -- Alessio Treglia Sun, 13 Mar 2011 11:10:25 +0100 accountsservice (0.6.1-1) unstable; urgency=low * Initial release (Closes: #606002). -- Alessio Treglia Mon, 17 Jan 2011 10:14:35 +0100 debian/rules0000775000000000000000000000206712252356330010256 0ustar #!/usr/bin/make -f # -*- makefile -*- export CPPFLAGS:=$(shell dpkg-buildflags --get CPPFLAGS) export CFLAGS:=$(shell dpkg-buildflags --get CFLAGS) $(CPPFLAGS) export CXXFLAGS:=$(shell dpkg-buildflags --get CXXFLAGS) export LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS) LDFLAGS+=-Wl,--as-needed %: dh $@ --parallel --with autoreconf override_dh_shlibdeps: dh_shlibdeps dh_girepository -l src:debian/libaccountsservice-dev/usr/share/gir-1.0 override_dh_auto_configure: dh_auto_configure -- \ --enable-gtk-doc \ --enable-systemd \ --enable-static=no \ --libexecdir=/usr/lib/accountsservice # Disabled to avoid FTBFS override_dh_auto_test: override_dh_installchangelogs: dh_installchangelogs NEWS override_dh_install: dh_install # patch is only applied conditionally, only install when present if [ -d debian/tmp/usr/share/language-tools ]; then \ cp -r debian/tmp/usr/share/language-tools debian/accountsservice/usr/share/; \ fi override_dh_strip: dh_strip -plibaccountsservice0 --dbg-package=libaccountsservice-dbg dh_strip --remaining-packages debian/accountsservice.postinst0000664000000000000000000000074612240704573014210 0ustar #!/bin/sh set -e get_pid() { [ -n "$1" ] || return 0 [ -S /var/run/dbus/system_bus_socket ] || return 0 dbus-send --system --dest=org.freedesktop.DBus --print-reply \ /org/freedesktop/DBus org.freedesktop.DBus.GetConnectionUnixProcessID \ string:$1 2>/dev/null | awk '/uint32/ {print $2}' } if [ "$1" = "configure" ]; then # stop accounts-daemon pid=$(get_pid org.freedesktop.Accounts) kill $pid 2>/dev/null || true fi #DEBHELPER# debian/libpam-pin.install0000775000000000000000000000015212252357170012615 0ustar #!/usr/bin/dh-exec /usr/lib/${DEB_HOST_MULTIARCH}/security/pam_pin.so /lib/${DEB_HOST_MULTIARCH}/security debian/gir1.2-accountsservice-1.0.install0000664000000000000000000000004412252710064015251 0ustar usr/lib/*/girepository-1.0 usr/lib/ debian/source/0000775000000000000000000000000012240704573010474 5ustar debian/source/format0000664000000000000000000000001412240704573011702 0ustar 3.0 (quilt) debian/libaccountsservice-doc.install0000664000000000000000000000010312240704573015210 0ustar doc/libaccountsservice/html/ usr/share/doc/libaccountsservice-doc/ debian/gbp.conf0000664000000000000000000000015212240704573010611 0ustar [DEFAULT] pristine-tar = True debian-branch = master.experimental upstream-branch = upstream.experimental debian/libaccountsservice0.symbols0000664000000000000000000006204512240704573014564 0ustar libaccountsservice.so.0 libaccountsservice0 #MINVER# accounts_accounts_call_cache_user@Base 0.6.24 accounts_accounts_call_cache_user_finish@Base 0.6.24 accounts_accounts_call_cache_user_sync@Base 0.6.24 accounts_accounts_call_create_user@Base 0.6.18 accounts_accounts_call_create_user_finish@Base 0.6.18 accounts_accounts_call_create_user_sync@Base 0.6.18 accounts_accounts_call_delete_user@Base 0.6.18 accounts_accounts_call_delete_user_finish@Base 0.6.18 accounts_accounts_call_delete_user_sync@Base 0.6.18 accounts_accounts_call_find_user_by_id@Base 0.6.18 accounts_accounts_call_find_user_by_id_finish@Base 0.6.18 accounts_accounts_call_find_user_by_id_sync@Base 0.6.18 accounts_accounts_call_find_user_by_name@Base 0.6.18 accounts_accounts_call_find_user_by_name_finish@Base 0.6.18 accounts_accounts_call_find_user_by_name_sync@Base 0.6.18 accounts_accounts_call_list_cached_users@Base 0.6.18 accounts_accounts_call_list_cached_users_finish@Base 0.6.18 accounts_accounts_call_list_cached_users_sync@Base 0.6.18 accounts_accounts_call_uncache_user@Base 0.6.24 accounts_accounts_call_uncache_user_finish@Base 0.6.24 accounts_accounts_call_uncache_user_sync@Base 0.6.24 accounts_accounts_complete_cache_user@Base 0.6.24 accounts_accounts_complete_create_user@Base 0.6.18 accounts_accounts_complete_delete_user@Base 0.6.18 accounts_accounts_complete_find_user_by_id@Base 0.6.18 accounts_accounts_complete_find_user_by_name@Base 0.6.18 accounts_accounts_complete_list_cached_users@Base 0.6.18 accounts_accounts_complete_uncache_user@Base 0.6.24 accounts_accounts_dup_daemon_version@Base 0.6.18 accounts_accounts_emit_user_added@Base 0.6.18 accounts_accounts_emit_user_deleted@Base 0.6.18 accounts_accounts_get_daemon_version@Base 0.6.18 accounts_accounts_get_type@Base 0.6.18 accounts_accounts_interface_info@Base 0.6.18 accounts_accounts_override_properties@Base 0.6.18 accounts_accounts_proxy_get_type@Base 0.6.18 accounts_accounts_proxy_new@Base 0.6.18 accounts_accounts_proxy_new_finish@Base 0.6.18 accounts_accounts_proxy_new_for_bus@Base 0.6.18 accounts_accounts_proxy_new_for_bus_finish@Base 0.6.18 accounts_accounts_proxy_new_for_bus_sync@Base 0.6.18 accounts_accounts_proxy_new_sync@Base 0.6.18 accounts_accounts_set_daemon_version@Base 0.6.18 accounts_accounts_skeleton_get_type@Base 0.6.18 accounts_accounts_skeleton_new@Base 0.6.18 accounts_user_call_begin_set_password@Base 0.6.29 accounts_user_call_begin_set_password_finish@Base 0.6.29 accounts_user_call_begin_set_password_sync@Base 0.6.29 accounts_user_call_continue_set_password@Base 0.6.29 accounts_user_call_continue_set_password_finish@Base 0.6.29 accounts_user_call_continue_set_password_sync@Base 0.6.29 accounts_user_call_set_account_type@Base 0.6.18 accounts_user_call_set_account_type_finish@Base 0.6.18 accounts_user_call_set_account_type_sync@Base 0.6.18 accounts_user_call_set_automatic_login@Base 0.6.18 accounts_user_call_set_automatic_login_finish@Base 0.6.18 accounts_user_call_set_automatic_login_sync@Base 0.6.18 accounts_user_call_set_background_file@Base 0.6.29 accounts_user_call_set_background_file_finish@Base 0.6.29 accounts_user_call_set_background_file_sync@Base 0.6.29 accounts_user_call_set_email@Base 0.6.18 accounts_user_call_set_email_finish@Base 0.6.18 accounts_user_call_set_email_sync@Base 0.6.18 accounts_user_call_set_formats_locale@Base 0.6.29 accounts_user_call_set_formats_locale_finish@Base 0.6.29 accounts_user_call_set_formats_locale_sync@Base 0.6.29 accounts_user_call_set_home_directory@Base 0.6.18 accounts_user_call_set_home_directory_finish@Base 0.6.18 accounts_user_call_set_home_directory_sync@Base 0.6.18 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_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 accounts_user_call_set_location@Base 0.6.18 accounts_user_call_set_location_finish@Base 0.6.18 accounts_user_call_set_location_sync@Base 0.6.18 accounts_user_call_set_locked@Base 0.6.18 accounts_user_call_set_locked_finish@Base 0.6.18 accounts_user_call_set_locked_sync@Base 0.6.18 accounts_user_call_set_password@Base 0.6.18 accounts_user_call_set_password_finish@Base 0.6.18 accounts_user_call_set_password_mode@Base 0.6.18 accounts_user_call_set_password_mode_finish@Base 0.6.18 accounts_user_call_set_password_mode_sync@Base 0.6.18 accounts_user_call_set_password_sync@Base 0.6.18 accounts_user_call_set_real_name@Base 0.6.18 accounts_user_call_set_real_name_finish@Base 0.6.18 accounts_user_call_set_real_name_sync@Base 0.6.18 accounts_user_call_set_shell@Base 0.6.18 accounts_user_call_set_shell_finish@Base 0.6.18 accounts_user_call_set_shell_sync@Base 0.6.18 accounts_user_call_set_user_name@Base 0.6.18 accounts_user_call_set_user_name_finish@Base 0.6.18 accounts_user_call_set_user_name_sync@Base 0.6.18 accounts_user_call_set_xhas_messages@Base 0.6.29 accounts_user_call_set_xhas_messages_finish@Base 0.6.29 accounts_user_call_set_xhas_messages_sync@Base 0.6.29 accounts_user_call_set_xkeyboard_layouts@Base 0.6.29 accounts_user_call_set_xkeyboard_layouts_finish@Base 0.6.29 accounts_user_call_set_xkeyboard_layouts_sync@Base 0.6.29 accounts_user_call_set_xsession@Base 0.6.18 accounts_user_call_set_xsession_finish@Base 0.6.18 accounts_user_call_set_xsession_sync@Base 0.6.18 accounts_user_complete_begin_set_password@Base 0.6.29 accounts_user_complete_continue_set_password@Base 0.6.29 accounts_user_complete_set_account_type@Base 0.6.18 accounts_user_complete_set_automatic_login@Base 0.6.18 accounts_user_complete_set_background_file@Base 0.6.29 accounts_user_complete_set_email@Base 0.6.18 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_language@Base 0.6.18 accounts_user_complete_set_location@Base 0.6.18 accounts_user_complete_set_locked@Base 0.6.18 accounts_user_complete_set_password@Base 0.6.18 accounts_user_complete_set_password_mode@Base 0.6.18 accounts_user_complete_set_real_name@Base 0.6.18 accounts_user_complete_set_shell@Base 0.6.18 accounts_user_complete_set_user_name@Base 0.6.18 accounts_user_complete_set_xhas_messages@Base 0.6.29 accounts_user_complete_set_xkeyboard_layouts@Base 0.6.29 accounts_user_complete_set_xsession@Base 0.6.18 accounts_user_dup_background_file@Base 0.6.29 accounts_user_dup_email@Base 0.6.18 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_language@Base 0.6.18 accounts_user_dup_location@Base 0.6.18 accounts_user_dup_login_history@Base 0.6.29 accounts_user_dup_password_hint@Base 0.6.18 accounts_user_dup_real_name@Base 0.6.18 accounts_user_dup_shell@Base 0.6.18 accounts_user_dup_user_name@Base 0.6.18 accounts_user_dup_xkeyboard_layouts@Base 0.6.29 accounts_user_dup_xsession@Base 0.6.18 accounts_user_emit_changed@Base 0.6.18 accounts_user_get_account_type@Base 0.6.18 accounts_user_get_automatic_login@Base 0.6.18 accounts_user_get_background_file@Base 0.6.29 accounts_user_get_email@Base 0.6.18 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_language@Base 0.6.18 accounts_user_get_local_account@Base 0.6.24 accounts_user_get_location@Base 0.6.18 accounts_user_get_locked@Base 0.6.18 accounts_user_get_login_frequency@Base 0.6.18 accounts_user_get_login_history@Base 0.6.29 accounts_user_get_login_time@Base 0.6.29 accounts_user_get_password_hint@Base 0.6.18 accounts_user_get_password_mode@Base 0.6.18 accounts_user_get_real_name@Base 0.6.18 accounts_user_get_shell@Base 0.6.18 accounts_user_get_system_account@Base 0.6.18 accounts_user_get_type@Base 0.6.18 accounts_user_get_uid@Base 0.6.18 accounts_user_get_user_name@Base 0.6.18 accounts_user_get_xhas_messages@Base 0.6.29 accounts_user_get_xkeyboard_layouts@Base 0.6.29 accounts_user_get_xsession@Base 0.6.18 accounts_user_interface_info@Base 0.6.18 accounts_user_override_properties@Base 0.6.18 accounts_user_proxy_get_type@Base 0.6.18 accounts_user_proxy_new@Base 0.6.18 accounts_user_proxy_new_finish@Base 0.6.18 accounts_user_proxy_new_for_bus@Base 0.6.18 accounts_user_proxy_new_for_bus_finish@Base 0.6.18 accounts_user_proxy_new_for_bus_sync@Base 0.6.18 accounts_user_proxy_new_sync@Base 0.6.18 accounts_user_set_account_type@Base 0.6.18 accounts_user_set_automatic_login@Base 0.6.18 accounts_user_set_background_file@Base 0.6.29 accounts_user_set_email@Base 0.6.18 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_language@Base 0.6.18 accounts_user_set_local_account@Base 0.6.24 accounts_user_set_location@Base 0.6.18 accounts_user_set_locked@Base 0.6.18 accounts_user_set_login_frequency@Base 0.6.18 accounts_user_set_login_history@Base 0.6.29 accounts_user_set_login_time@Base 0.6.29 accounts_user_set_password_hint@Base 0.6.18 accounts_user_set_password_mode@Base 0.6.18 accounts_user_set_real_name@Base 0.6.18 accounts_user_set_shell@Base 0.6.18 accounts_user_set_system_account@Base 0.6.18 accounts_user_set_uid@Base 0.6.18 accounts_user_set_user_name@Base 0.6.18 accounts_user_set_xhas_messages@Base 0.6.29 accounts_user_set_xkeyboard_layouts@Base 0.6.29 accounts_user_set_xsession@Base 0.6.18 accounts_user_skeleton_get_type@Base 0.6.18 accounts_user_skeleton_new@Base 0.6.18 act_user_account_type_get_type@Base 0.6.8 act_user_collate@Base 0.6.8 act_user_get_account_type@Base 0.6.8 act_user_get_automatic_login@Base 0.6.8 act_user_get_background_file@Base 0.6.29 act_user_get_email@Base 0.6.8 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_language@Base 0.6.8 act_user_get_location@Base 0.6.8 act_user_get_locked@Base 0.6.8 act_user_get_login_frequency@Base 0.6.8 act_user_get_login_history@Base 0.6.29 act_user_get_login_time@Base 0.6.29 act_user_get_num_sessions@Base 0.6.8 act_user_get_num_sessions_anywhere@Base 0.6.34 act_user_get_object_path@Base 0.6.8 act_user_get_password_hint@Base 0.6.8 act_user_get_password_mode@Base 0.6.8 act_user_get_primary_session_id@Base 0.6.8 act_user_get_real_name@Base 0.6.8 act_user_get_shell@Base 0.6.8 act_user_get_type@Base 0.6.8 act_user_get_uid@Base 0.6.8 act_user_get_user_name@Base 0.6.8 act_user_get_x_has_messages@Base 0.6.29 act_user_get_x_keyboard_layouts@Base 0.6.29 act_user_get_x_session@Base 0.6.8 act_user_is_loaded@Base 0.6.8 act_user_is_local_account@Base 0.6.24 act_user_is_logged_in@Base 0.6.8 act_user_is_logged_in_anywhere@Base 0.6.34 act_user_is_system_account@Base 0.6.9 act_user_manager_activate_user_session@Base 0.6.8 act_user_manager_cache_user@Base 0.6.24 act_user_manager_cache_user_async@Base 0.6.29 act_user_manager_cache_user_finish@Base 0.6.29 act_user_manager_can_switch@Base 0.6.8 act_user_manager_create_user@Base 0.6.12 act_user_manager_create_user_async@Base 0.6.29 act_user_manager_create_user_finish@Base 0.6.29 act_user_manager_delete_user@Base 0.6.13 act_user_manager_delete_user_async@Base 0.6.29 act_user_manager_delete_user_finish@Base 0.6.29 act_user_manager_error_get_type@Base 0.6.18 act_user_manager_error_quark@Base 0.6.8 act_user_manager_get_default@Base 0.6.8 act_user_manager_get_type@Base 0.6.8 act_user_manager_get_user@Base 0.6.8 act_user_manager_get_user_by_id@Base 0.6.34 act_user_manager_goto_login_session@Base 0.6.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_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 act_user_set_automatic_login@Base 0.6.8 act_user_set_background_file@Base 0.6.29 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_language@Base 0.6.8 act_user_set_location@Base 0.6.8 act_user_set_locked@Base 0.6.8 act_user_set_multiple_passwords@Base 0.6.29 act_user_set_password@Base 0.6.8 act_user_set_password_mode@Base 0.6.8 act_user_set_real_name@Base 0.6.8 act_user_set_user_name@Base 0.6.8 act_user_set_x_has_messages@Base 0.6.29 act_user_set_x_keyboard_layouts@Base 0.6.29 act_user_set_x_session@Base 0.6.8 console_kit_manager_call_can_restart@Base 0.6.18 console_kit_manager_call_can_restart_finish@Base 0.6.18 console_kit_manager_call_can_restart_sync@Base 0.6.18 console_kit_manager_call_can_stop@Base 0.6.18 console_kit_manager_call_can_stop_finish@Base 0.6.18 console_kit_manager_call_can_stop_sync@Base 0.6.18 console_kit_manager_call_close_session@Base 0.6.18 console_kit_manager_call_close_session_finish@Base 0.6.18 console_kit_manager_call_close_session_sync@Base 0.6.18 console_kit_manager_call_get_current_session@Base 0.6.18 console_kit_manager_call_get_current_session_finish@Base 0.6.18 console_kit_manager_call_get_current_session_sync@Base 0.6.18 console_kit_manager_call_get_seats@Base 0.6.18 console_kit_manager_call_get_seats_finish@Base 0.6.18 console_kit_manager_call_get_seats_sync@Base 0.6.18 console_kit_manager_call_get_session_for_cookie@Base 0.6.18 console_kit_manager_call_get_session_for_cookie_finish@Base 0.6.18 console_kit_manager_call_get_session_for_cookie_sync@Base 0.6.18 console_kit_manager_call_get_session_for_unix_process@Base 0.6.18 console_kit_manager_call_get_session_for_unix_process_finish@Base 0.6.18 console_kit_manager_call_get_session_for_unix_process_sync@Base 0.6.18 console_kit_manager_call_get_sessions@Base 0.6.18 console_kit_manager_call_get_sessions_finish@Base 0.6.18 console_kit_manager_call_get_sessions_for_unix_user@Base 0.6.18 console_kit_manager_call_get_sessions_for_unix_user_finish@Base 0.6.18 console_kit_manager_call_get_sessions_for_unix_user_sync@Base 0.6.18 console_kit_manager_call_get_sessions_for_user@Base 0.6.18 console_kit_manager_call_get_sessions_for_user_finish@Base 0.6.18 console_kit_manager_call_get_sessions_for_user_sync@Base 0.6.18 console_kit_manager_call_get_sessions_sync@Base 0.6.18 console_kit_manager_call_get_system_idle_hint@Base 0.6.18 console_kit_manager_call_get_system_idle_hint_finish@Base 0.6.18 console_kit_manager_call_get_system_idle_hint_sync@Base 0.6.18 console_kit_manager_call_get_system_idle_since_hint@Base 0.6.18 console_kit_manager_call_get_system_idle_since_hint_finish@Base 0.6.18 console_kit_manager_call_get_system_idle_since_hint_sync@Base 0.6.18 console_kit_manager_call_open_session@Base 0.6.18 console_kit_manager_call_open_session_finish@Base 0.6.18 console_kit_manager_call_open_session_sync@Base 0.6.18 console_kit_manager_call_open_session_with_parameters@Base 0.6.18 console_kit_manager_call_open_session_with_parameters_finish@Base 0.6.18 console_kit_manager_call_open_session_with_parameters_sync@Base 0.6.18 console_kit_manager_call_restart@Base 0.6.18 console_kit_manager_call_restart_finish@Base 0.6.18 console_kit_manager_call_restart_sync@Base 0.6.18 console_kit_manager_call_stop@Base 0.6.18 console_kit_manager_call_stop_finish@Base 0.6.18 console_kit_manager_call_stop_sync@Base 0.6.18 console_kit_manager_complete_can_restart@Base 0.6.18 console_kit_manager_complete_can_stop@Base 0.6.18 console_kit_manager_complete_close_session@Base 0.6.18 console_kit_manager_complete_get_current_session@Base 0.6.18 console_kit_manager_complete_get_seats@Base 0.6.18 console_kit_manager_complete_get_session_for_cookie@Base 0.6.18 console_kit_manager_complete_get_session_for_unix_process@Base 0.6.18 console_kit_manager_complete_get_sessions@Base 0.6.18 console_kit_manager_complete_get_sessions_for_unix_user@Base 0.6.18 console_kit_manager_complete_get_sessions_for_user@Base 0.6.18 console_kit_manager_complete_get_system_idle_hint@Base 0.6.18 console_kit_manager_complete_get_system_idle_since_hint@Base 0.6.18 console_kit_manager_complete_open_session@Base 0.6.18 console_kit_manager_complete_open_session_with_parameters@Base 0.6.18 console_kit_manager_complete_restart@Base 0.6.18 console_kit_manager_complete_stop@Base 0.6.18 console_kit_manager_emit_seat_added@Base 0.6.18 console_kit_manager_emit_seat_removed@Base 0.6.18 console_kit_manager_emit_system_idle_hint_changed@Base 0.6.18 console_kit_manager_get_type@Base 0.6.18 console_kit_manager_interface_info@Base 0.6.18 console_kit_manager_override_properties@Base 0.6.18 console_kit_manager_proxy_get_type@Base 0.6.18 console_kit_manager_proxy_new@Base 0.6.18 console_kit_manager_proxy_new_finish@Base 0.6.18 console_kit_manager_proxy_new_for_bus@Base 0.6.18 console_kit_manager_proxy_new_for_bus_finish@Base 0.6.18 console_kit_manager_proxy_new_for_bus_sync@Base 0.6.18 console_kit_manager_proxy_new_sync@Base 0.6.18 console_kit_manager_skeleton_get_type@Base 0.6.18 console_kit_manager_skeleton_new@Base 0.6.18 console_kit_seat_call_activate_session@Base 0.6.18 console_kit_seat_call_activate_session_finish@Base 0.6.18 console_kit_seat_call_activate_session_sync@Base 0.6.18 console_kit_seat_call_can_activate_sessions@Base 0.6.18 console_kit_seat_call_can_activate_sessions_finish@Base 0.6.18 console_kit_seat_call_can_activate_sessions_sync@Base 0.6.18 console_kit_seat_call_get_active_session@Base 0.6.18 console_kit_seat_call_get_active_session_finish@Base 0.6.18 console_kit_seat_call_get_active_session_sync@Base 0.6.18 console_kit_seat_call_get_devices@Base 0.6.18 console_kit_seat_call_get_devices_finish@Base 0.6.18 console_kit_seat_call_get_devices_sync@Base 0.6.18 console_kit_seat_call_get_id@Base 0.6.18 console_kit_seat_call_get_id_finish@Base 0.6.18 console_kit_seat_call_get_id_sync@Base 0.6.18 console_kit_seat_call_get_sessions@Base 0.6.18 console_kit_seat_call_get_sessions_finish@Base 0.6.18 console_kit_seat_call_get_sessions_sync@Base 0.6.18 console_kit_seat_complete_activate_session@Base 0.6.18 console_kit_seat_complete_can_activate_sessions@Base 0.6.18 console_kit_seat_complete_get_active_session@Base 0.6.18 console_kit_seat_complete_get_devices@Base 0.6.18 console_kit_seat_complete_get_id@Base 0.6.18 console_kit_seat_complete_get_sessions@Base 0.6.18 console_kit_seat_emit_active_session_changed@Base 0.6.18 console_kit_seat_emit_device_added@Base 0.6.18 console_kit_seat_emit_device_removed@Base 0.6.18 console_kit_seat_emit_session_added@Base 0.6.18 console_kit_seat_emit_session_removed@Base 0.6.18 console_kit_seat_get_type@Base 0.6.18 console_kit_seat_interface_info@Base 0.6.18 console_kit_seat_override_properties@Base 0.6.18 console_kit_seat_proxy_get_type@Base 0.6.18 console_kit_seat_proxy_new@Base 0.6.18 console_kit_seat_proxy_new_finish@Base 0.6.18 console_kit_seat_proxy_new_for_bus@Base 0.6.18 console_kit_seat_proxy_new_for_bus_finish@Base 0.6.18 console_kit_seat_proxy_new_for_bus_sync@Base 0.6.18 console_kit_seat_proxy_new_sync@Base 0.6.18 console_kit_seat_skeleton_get_type@Base 0.6.18 console_kit_seat_skeleton_new@Base 0.6.18 console_kit_session_call_activate@Base 0.6.18 console_kit_session_call_activate_finish@Base 0.6.18 console_kit_session_call_activate_sync@Base 0.6.18 console_kit_session_call_get_creation_time@Base 0.6.18 console_kit_session_call_get_creation_time_finish@Base 0.6.18 console_kit_session_call_get_creation_time_sync@Base 0.6.18 console_kit_session_call_get_display_device@Base 0.6.18 console_kit_session_call_get_display_device_finish@Base 0.6.18 console_kit_session_call_get_display_device_sync@Base 0.6.18 console_kit_session_call_get_id@Base 0.6.18 console_kit_session_call_get_id_finish@Base 0.6.18 console_kit_session_call_get_id_sync@Base 0.6.18 console_kit_session_call_get_idle_hint@Base 0.6.18 console_kit_session_call_get_idle_hint_finish@Base 0.6.18 console_kit_session_call_get_idle_hint_sync@Base 0.6.18 console_kit_session_call_get_idle_since_hint@Base 0.6.18 console_kit_session_call_get_idle_since_hint_finish@Base 0.6.18 console_kit_session_call_get_idle_since_hint_sync@Base 0.6.18 console_kit_session_call_get_login_session_id@Base 0.6.18 console_kit_session_call_get_login_session_id_finish@Base 0.6.18 console_kit_session_call_get_login_session_id_sync@Base 0.6.18 console_kit_session_call_get_remote_host_name@Base 0.6.18 console_kit_session_call_get_remote_host_name_finish@Base 0.6.18 console_kit_session_call_get_remote_host_name_sync@Base 0.6.18 console_kit_session_call_get_seat_id@Base 0.6.18 console_kit_session_call_get_seat_id_finish@Base 0.6.18 console_kit_session_call_get_seat_id_sync@Base 0.6.18 console_kit_session_call_get_session_type@Base 0.6.18 console_kit_session_call_get_session_type_finish@Base 0.6.18 console_kit_session_call_get_session_type_sync@Base 0.6.18 console_kit_session_call_get_unix_user@Base 0.6.18 console_kit_session_call_get_unix_user_finish@Base 0.6.18 console_kit_session_call_get_unix_user_sync@Base 0.6.18 console_kit_session_call_get_user@Base 0.6.18 console_kit_session_call_get_user_finish@Base 0.6.18 console_kit_session_call_get_user_sync@Base 0.6.18 console_kit_session_call_get_x11_display@Base 0.6.18 console_kit_session_call_get_x11_display_device@Base 0.6.18 console_kit_session_call_get_x11_display_device_finish@Base 0.6.18 console_kit_session_call_get_x11_display_device_sync@Base 0.6.18 console_kit_session_call_get_x11_display_finish@Base 0.6.18 console_kit_session_call_get_x11_display_sync@Base 0.6.18 console_kit_session_call_is_active@Base 0.6.18 console_kit_session_call_is_active_finish@Base 0.6.18 console_kit_session_call_is_active_sync@Base 0.6.18 console_kit_session_call_is_local@Base 0.6.18 console_kit_session_call_is_local_finish@Base 0.6.18 console_kit_session_call_is_local_sync@Base 0.6.18 console_kit_session_call_lock@Base 0.6.18 console_kit_session_call_lock_finish@Base 0.6.18 console_kit_session_call_lock_sync@Base 0.6.18 console_kit_session_call_set_idle_hint@Base 0.6.18 console_kit_session_call_set_idle_hint_finish@Base 0.6.18 console_kit_session_call_set_idle_hint_sync@Base 0.6.18 console_kit_session_call_unlock@Base 0.6.18 console_kit_session_call_unlock_finish@Base 0.6.18 console_kit_session_call_unlock_sync@Base 0.6.18 console_kit_session_complete_activate@Base 0.6.18 console_kit_session_complete_get_creation_time@Base 0.6.18 console_kit_session_complete_get_display_device@Base 0.6.18 console_kit_session_complete_get_id@Base 0.6.18 console_kit_session_complete_get_idle_hint@Base 0.6.18 console_kit_session_complete_get_idle_since_hint@Base 0.6.18 console_kit_session_complete_get_login_session_id@Base 0.6.18 console_kit_session_complete_get_remote_host_name@Base 0.6.18 console_kit_session_complete_get_seat_id@Base 0.6.18 console_kit_session_complete_get_session_type@Base 0.6.18 console_kit_session_complete_get_unix_user@Base 0.6.18 console_kit_session_complete_get_user@Base 0.6.18 console_kit_session_complete_get_x11_display@Base 0.6.18 console_kit_session_complete_get_x11_display_device@Base 0.6.18 console_kit_session_complete_is_active@Base 0.6.18 console_kit_session_complete_is_local@Base 0.6.18 console_kit_session_complete_lock@Base 0.6.18 console_kit_session_complete_set_idle_hint@Base 0.6.18 console_kit_session_complete_unlock@Base 0.6.18 console_kit_session_dup_display_device@Base 0.6.18 console_kit_session_dup_remote_host_name@Base 0.6.18 console_kit_session_dup_session_type@Base 0.6.18 console_kit_session_dup_x11_display@Base 0.6.18 console_kit_session_dup_x11_display_device@Base 0.6.18 console_kit_session_emit_active_changed@Base 0.6.18 console_kit_session_emit_idle_hint_changed@Base 0.6.18 console_kit_session_emit_lock@Base 0.6.18 console_kit_session_emit_unlock@Base 0.6.18 console_kit_session_get_active@Base 0.6.18 console_kit_session_get_display_device@Base 0.6.18 console_kit_session_get_idle_hint@Base 0.6.18 console_kit_session_get_is_local@Base 0.6.18 console_kit_session_get_remote_host_name@Base 0.6.18 console_kit_session_get_session_type@Base 0.6.18 console_kit_session_get_type@Base 0.6.18 console_kit_session_get_unix_user@Base 0.6.18 console_kit_session_get_user@Base 0.6.18 console_kit_session_get_x11_display@Base 0.6.18 console_kit_session_get_x11_display_device@Base 0.6.18 console_kit_session_interface_info@Base 0.6.18 console_kit_session_override_properties@Base 0.6.18 console_kit_session_proxy_get_type@Base 0.6.18 console_kit_session_proxy_new@Base 0.6.18 console_kit_session_proxy_new_finish@Base 0.6.18 console_kit_session_proxy_new_for_bus@Base 0.6.18 console_kit_session_proxy_new_for_bus_finish@Base 0.6.18 console_kit_session_proxy_new_for_bus_sync@Base 0.6.18 console_kit_session_proxy_new_sync@Base 0.6.18 console_kit_session_set_active@Base 0.6.18 console_kit_session_set_display_device@Base 0.6.18 console_kit_session_set_idle_hint@Base 0.6.18 console_kit_session_set_is_local@Base 0.6.18 console_kit_session_set_remote_host_name@Base 0.6.18 console_kit_session_set_session_type@Base 0.6.18 console_kit_session_set_unix_user@Base 0.6.18 console_kit_session_set_user@Base 0.6.18 console_kit_session_set_x11_display@Base 0.6.18 console_kit_session_set_x11_display_device@Base 0.6.18 console_kit_session_skeleton_get_type@Base 0.6.18 console_kit_session_skeleton_new@Base 0.6.18 debian/libaccountsservice0.install0000664000000000000000000000002112252356411014521 0ustar usr/lib/*/*.so.* debian/accountsservice.install0000664000000000000000000000012512252355450013761 0ustar etc usr/lib/accountsservice usr/share/dbus-1 usr/share/locale usr/share/polkit-1 var debian/control0000664000000000000000000001035512252711440010575 0ustar Source: accountsservice Section: admin Priority: optional Maintainer: Ubuntu Developers XSBC-Original-Maintainer: Alessio Treglia Build-Depends: debhelper (>= 7.0.50~), dh-autoreconf, dh-exec, gir1.2-freedesktop, gir1.2-glib-2.0 (>= 1.34), gobject-introspection (>= 0.9.12-4~), gtk-doc-tools, intltool, libgcr-3-dev, libgcrypt11-dev, libgirepository1.0-dev (>= 0.9.12), libglib2.0-dev (>= 2.37.3), libgnutls-dev, libpam0g-dev, libpolkit-gobject-1-dev, libsystemd-login-dev (>= 186), libsystemd-daemon-dev, xmlto Standards-Version: 3.9.4 Homepage: http://cgit.freedesktop.org/accountsservice/ Vcs-Git: git://anonscm.debian.org/collab-maint/accountsservice.git Vcs-Browser: http://anonscm.debian.org/gitweb/?p=collab-maint/accountsservice.git Package: accountsservice Architecture: any Depends: dbus, libaccountsservice0 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Suggests: gnome-control-center Description: query and manipulate user account information The AccountService 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. Package: libaccountsservice0 Section: libs Architecture: any Multi-Arch: same Depends: ${misc:Depends}, ${shlibs:Depends} Breaks: accountsservice (<< 0.6.5) Description: query and manipulate user account information - shared libraries The AccountService 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. . This package provides the shared libraries of the AccountService library. Package: libaccountsservice-dev Section: libdevel Architecture: any Multi-Arch: same Depends: gir1.2-accountsservice-1.0 (= ${binary:Version}), libaccountsservice0 (= ${binary:Version}), libglib2.0-dev (>= 2.25.11), libpolkit-gobject-1-dev, ${misc:Depends} Description: query and manipulate user account information - header files The AccountService 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. . This package provides the development files for the AccountService library. Package: gir1.2-accountsservice-1.0 Section: introspection Architecture: any Multi-Arch: foreign Depends: ${gir:Depends}, ${misc:Depends}, ${shlibs:Depends} Replaces: gir1.2-accountservice-1.0 (<< 0.6.12-4) Breaks: gir1.2-accountservice-1.0 (<< 0.6.12-4) Description: GObject introspection data for AccountService The AccountService 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. . This package provides the introspection data for the AccountService library. Package: libaccountsservice-dbg Section: debug Priority: extra Architecture: any Multi-Arch: same Depends: libaccountsservice0 (= ${binary:Version}), ${misc:Depends} Description: query and manipulate user account information - debug The AccountService 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. . This package provides the debugging symbols for the AccountService library. Package: libaccountsservice-doc Section: doc Architecture: all Depends: ${misc:Depends} Description: query and manipulate user account information - documentation The AccountService 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. . This package provides the developers reference for the AccountService library. Package: libpam-pin Architecture: any Multi-Arch: same Depends: ${misc:Depends}, ${shlibs:Depends}, Description: PAM module for using a PIN code A Pluggable Authentication Module for PIN codes. Useful for presenting a different interface for PIN codes than passwords. debian/libaccountsservice-dev.install0000664000000000000000000000010212252356463015224 0ustar usr/include usr/lib/*/*.so usr/lib/*/pkgconfig usr/share/gir-1.0 debian/compat0000664000000000000000000000000212252356016010370 0ustar 9 debian/watch0000664000000000000000000000016512240704573010227 0ustar version=3 http://cgit.freedesktop.org/accountsservice \ /accountsservice/snapshot/accountsservice-([\d\.]+)\.tar\.gz debian/docs0000664000000000000000000000001412240704573010042 0ustar README TODO debian/patches/0000775000000000000000000000000012266267520010627 5ustar debian/patches/0005-gdm_config_file_path_ubuntu.patch0000664000000000000000000000205412240704573017740 0ustar Description: Fix path to the GDM configuration file, which is different in Debian. Author: Josselin Mouette Bug-Debian: http://bugs.debian.org/627311 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=49993 --- src/daemon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- accountsservice.orig/src/daemon.c +++ accountsservice/src/daemon.c @@ -49,7 +49,7 @@ #define PATH_SHADOW "/etc/shadow" #define PATH_NOLOGIN "/sbin/nologin" #define PATH_FALSE "/bin/false" -#define PATH_GDM_CUSTOM "/etc/gdm3/daemon.conf" +#define PATH_GDM_CUSTOM "/etc/gdm/custom.conf" #define USERDIR LOCALSTATEDIR "/lib/AccountsService/users" @@ -445,7 +445,7 @@ reload_autologin_timeout (Daemon *daemon daemon->priv->autologin_id = 0; if (!load_autologin (daemon, &name, &enabled, &error)) { - g_debug ("failed to load gdms daemon.conf: %s", error->message); + g_debug ("failed to load gdms custom.conf: %s", error->message); g_error_free (error); g_free (name); debian/patches/2001-filtering_out_users.patch0000664000000000000000000004650512240704573016331 0ustar 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)); debian/patches/0002-create-and-manage-groups-like-on-a-ubuntu-system.patch0000664000000000000000000001573712240704676023426 0ustar From: Frederic Peters Bug-Debian: http://bugs.debian.org/618764 Forwarded: not-needed Description: Create and manage groups like on an Ubuntu system. --- src/daemon.c | 25 +++++++++---------------- src/user.c | 22 +++++++++++----------- src/util.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/util.h | 9 +++++++++ 4 files changed, 71 insertions(+), 27 deletions(-) Index: accountsservice-0.6.35/src/daemon.c =================================================================== --- accountsservice-0.6.35.orig/src/daemon.c 2013-11-13 15:16:26.656124544 +0100 +++ accountsservice-0.6.35/src/daemon.c 2013-11-13 15:16:26.648124544 +0100 @@ -1065,22 +1065,8 @@ argv[1] = "-m"; argv[2] = "-c"; argv[3] = cd->real_name; - if (cd->account_type == ACCOUNT_TYPE_ADMINISTRATOR) { - argv[4] = "-G"; - argv[5] = ADMIN_GROUP; - argv[6] = "--"; - argv[7] = cd->user_name; - argv[8] = NULL; - } - else if (cd->account_type == ACCOUNT_TYPE_STANDARD) { - argv[4] = "--"; - argv[5] = cd->user_name; - argv[6] = NULL; - } - else { - throw_error (context, ERROR_FAILED, "Don't know how to add user of type %d", cd->account_type); - return; - } + argv[4] = cd->user_name; + argv[5] = NULL; error = NULL; if (!spawn_with_login_uid (context, argv, &error)) { @@ -1089,6 +1075,13 @@ return; } + if (cd->account_type == ACCOUNT_TYPE_ADMINISTRATOR) { + add_user_to_group (context, cd->user_name, ADMIN_GROUP); + add_user_to_group (context, cd->user_name, "adm"); + add_user_to_group (context, cd->user_name, "lpadmin"); + add_user_to_group (context, cd->user_name, "sambashare"); + } + user = daemon_local_find_user_by_name (daemon, cd->user_name); user_update_local_account_property (user, TRUE); user_update_system_account_property (user, FALSE); Index: accountsservice-0.6.35/src/user.c =================================================================== --- accountsservice-0.6.35.orig/src/user.c 2013-11-13 15:16:26.656124544 +0100 +++ accountsservice-0.6.35/src/user.c 2013-11-13 15:16:26.648124544 +0100 @@ -124,7 +124,8 @@ account_type_from_pwent (struct passwd *pwent) { struct group *grp; - gid_t wheel; + gid_t sudo; + gid_t admin; gid_t *groups; gint ngroups; gint i; @@ -139,12 +140,21 @@ g_debug (ADMIN_GROUP " group not found"); return ACCOUNT_TYPE_STANDARD; } - wheel = grp->gr_gid; + sudo = grp->gr_gid; + + /* Ubuntu prior to 12.04 used "admin" */ + grp = getgrnam ("admin"); + if (grp == NULL) { + g_debug ("admin group not found"); + admin = -1; + } else { + admin = grp->gr_gid; + } ngroups = get_user_groups (pwent->pw_name, pwent->pw_gid, &groups); for (i = 0; i < ngroups; i++) { - if (groups[i] == wheel) { + if (groups[i] == sudo || groups[i] == admin) { g_free (groups); return ACCOUNT_TYPE_ADMINISTRATOR; } @@ -1693,7 +1703,7 @@ gid_t *groups; gint ngroups; GString *str; - gid_t wheel; + gid_t admin; struct group *grp; gint i; const gchar *argv[6]; @@ -1705,22 +1715,22 @@ grp = getgrnam (ADMIN_GROUP); if (grp == NULL) { - throw_error (context, ERROR_FAILED, "failed to set account type: wheel group not found"); + throw_error (context, ERROR_FAILED, "failed to set account type: sudo group not found"); return; } - wheel = grp->gr_gid; + admin = grp->gr_gid; ngroups = get_user_groups (user->user_name, user->gid, &groups); str = g_string_new (""); for (i = 0; i < ngroups; i++) { - if (groups[i] == wheel) + if (groups[i] == admin) continue; g_string_append_printf (str, "%d,", groups[i]); } switch (account_type) { case ACCOUNT_TYPE_ADMINISTRATOR: - g_string_append_printf (str, "%d", wheel); + g_string_append_printf (str, "%d", admin); break; case ACCOUNT_TYPE_STANDARD: default: Index: accountsservice-0.6.35/src/util.c =================================================================== --- accountsservice-0.6.35.orig/src/util.c 2013-11-13 15:16:26.656124544 +0100 +++ accountsservice-0.6.35/src/util.c 2013-11-13 15:16:26.648124544 +0100 @@ -313,3 +313,45 @@ return TRUE; } + +void +add_user_to_group (GDBusMethodInvocation *context, + const char *user_name, + const char *group_name) +{ + GError *error; + const gchar *argv[4]; + + argv[0] = (gchar*) "/usr/sbin/adduser"; + argv[1] = (gchar*) user_name; + argv[2] = (gchar*) group_name; + argv[3] = NULL; + + error = NULL; + if (!spawn_with_login_uid (context, argv, &error)) { + g_warning ("failed to add user %s to group %s", user_name, group_name); + g_error_free (error); + return; + } +} + +void +remove_user_from_group (GDBusMethodInvocation *context, + const char *user_name, + const char *group_name) +{ + GError *error; + const gchar *argv[4]; + + argv[0] = (gchar*) "/usr/sbin/deluser"; + argv[1] = (gchar*) user_name; + argv[2] = (gchar*) group_name; + argv[3] = NULL; + + error = NULL; + if (!spawn_with_login_uid (context, argv, &error)) { + g_warning ("failed to remove user %s from group %s", user_name, group_name); + g_error_free (error); + return; + } +} Index: accountsservice-0.6.35/src/util.h =================================================================== --- accountsservice-0.6.35.orig/src/util.h 2013-11-13 15:16:26.656124544 +0100 +++ accountsservice-0.6.35/src/util.h 2013-11-13 15:16:26.648124544 +0100 @@ -40,6 +40,15 @@ gid_t group, gid_t **groups); +void add_user_to_group (GDBusMethodInvocation *context, + const char *user_name, + const char *group_name); + +void remove_user_from_group (GDBusMethodInvocation *context, + const char *user_name, + const char *group_name); + + G_END_DECLS #endif /* __UTIL_H__ */ debian/patches/0013-add-has-message-support.patch0000664000000000000000000002453412240704737016674 0ustar Index: accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml =================================================================== --- accountsservice-0.6.35.orig/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:17:01.604125597 +0100 +++ accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:17:01.592125596 +0100 @@ -331,6 +331,41 @@ + + + + + + Whether the user has messages waiting for them. + + + + + + + Sets whether the user has messages waiting for them. + + + + The caller needs one of the following PolicyKit authorizations: + + + org.freedesktop.accounts.change-own-user-data + To change his or her own status + + + org.freedesktop.accounts.user-administration + To change the status of another user + + + + + if the caller lacks the appropriate PolicyKit authorization + if the operation failed + + + + @@ -793,6 +828,16 @@ + + + + + + + Whether the user has messages waiting for them. + + + Index: accountsservice-0.6.35/src/libaccountsservice/act-user.c =================================================================== --- accountsservice-0.6.35.orig/src/libaccountsservice/act-user.c 2013-11-13 15:17:01.604125597 +0100 +++ accountsservice-0.6.35/src/libaccountsservice/act-user.c 2013-11-13 15:17:01.596125596 +0100 @@ -91,6 +91,7 @@ PROP_LOGIN_FREQUENCY, PROP_LOGIN_TIME, PROP_LOGIN_HISTORY, + PROP_X_HAS_MESSAGES, PROP_X_KEYBOARD_LAYOUTS, PROP_BACKGROUND_FILE, PROP_ICON_FILE, @@ -140,6 +141,7 @@ guint uid_set : 1; + guint x_has_messages : 1; guint is_loaded : 1; guint locked : 1; guint automatic_login : 1; @@ -308,6 +310,9 @@ case PROP_LOCATION: g_value_set_string (value, user->location); break; + case PROP_X_HAS_MESSAGES: + g_value_set_boolean (value, user->x_has_messages); + break; case PROP_X_KEYBOARD_LAYOUTS: g_value_set_boxed (value, g_strdupv (user->x_keyboard_layouts)); break; @@ -465,6 +470,13 @@ NULL, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, + PROP_X_HAS_MESSAGES, + g_param_spec_boolean ("xhas-messages", + "Has Messages", + "Whether the user has messages waiting.", + FALSE, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, PROP_X_KEYBOARD_LAYOUTS, g_param_spec_boxed ("xkeyboard-layouts", "Keyboard layouts", @@ -1059,6 +1071,22 @@ } /** + * act_user_get_x_has_messages: + * @user: a #ActUser + * + * Returns whether @user has messages waiting for them. + * + * Returns: whether messages exist + */ +gboolean +act_user_get_x_has_messages (ActUser *user) +{ + g_return_val_if_fail (ACT_IS_USER (user), FALSE); + + return user->x_has_messages; +} + +/** * act_user_get_x_keyboard_layouts: * @user: a #ActUser * @@ -1370,6 +1398,14 @@ user->login_history = g_variant_ref (new_login_history); g_object_notify (G_OBJECT (user), "login-history"); } + } else if (strcmp (key, "XHasMessages") == 0) { + gboolean new_has_messages; + + new_has_messages = g_variant_get_boolean (value); + if (new_has_messages != user->x_has_messages) { + user->x_has_messages = new_has_messages; + g_object_notify (G_OBJECT (user), "xhas-messages"); + } } else if (strcmp (key, "XKeyboardLayouts") == 0) { const char **new_x_keyboard_layouts; @@ -1741,6 +1777,34 @@ g_error_free (error); return; } +} + +/** + * act_user_set_x_has_messages: + * @user: the user object to alter. + * @has_messages: whether the user has messages waiting + * + * Sets a new has-messages status for @user. + * + * Note this function is synchronous and ignores errors. + **/ +void +act_user_set_x_has_messages (ActUser *user, + gboolean has_messages) +{ + GError *error = NULL; + + g_return_if_fail (ACT_IS_USER (user)); + g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy)); + + if (!accounts_user_call_set_xhas_messages_sync (user->accounts_proxy, + has_messages, + NULL, + &error)) { + g_warning ("SetXHasMessages call failed: %s", error->message); + g_error_free (error); + return; + } } /** Index: accountsservice-0.6.35/src/user.c =================================================================== --- accountsservice-0.6.35.orig/src/user.c 2013-11-13 15:17:01.604125597 +0100 +++ accountsservice-0.6.35/src/user.c 2013-11-13 15:17:01.600125597 +0100 @@ -64,6 +64,7 @@ PROP_LOGIN_FREQUENCY, PROP_LOGIN_TIME, PROP_LOGIN_HISTORY, + PROP_X_HAS_MESSAGES, PROP_X_KEYBOARD_LAYOUTS, PROP_BACKGROUND_FILE, PROP_ICON_FILE, @@ -100,6 +101,7 @@ gchar *x_session; gchar *location; guint64 login_frequency; + gboolean x_has_messages; gchar **x_keyboard_layouts; gchar *background_file; gint64 login_time; @@ -1812,6 +1814,52 @@ } static void +user_change_x_has_messages_authorized_cb (Daemon *daemon, + User *user, + GDBusMethodInvocation *context, + gpointer data) +{ + user->x_has_messages = GPOINTER_TO_INT (data); + + accounts_user_emit_changed (ACCOUNTS_USER (user)); + + g_object_notify (G_OBJECT (user), "xhas-messages"); + + accounts_user_complete_set_xhas_messages (ACCOUNTS_USER (user), context); +} + +gboolean +user_set_xhas_messages (AccountsUser *auser, + GDBusMethodInvocation *context, + gboolean has_messages) +{ + User *user = (User*)auser; + int uid; + const gchar *action_id; + + if (!get_caller_uid (context, &uid)) { + throw_error (context, ERROR_FAILED, "identifying caller failed"); + return FALSE; + } + + if (user->uid == (uid_t) uid) + action_id = "org.freedesktop.accounts.change-own-user-data"; + else + action_id = "org.freedesktop.accounts.user-administration"; + + daemon_local_check_auth (user->daemon, + user, + action_id, + TRUE, + user_change_x_has_messages_authorized_cb, + context, + GINT_TO_POINTER (has_messages), + NULL); + + return TRUE; +} + +static void user_change_x_keyboard_layouts_authorized_cb (Daemon *daemon, User *user, GDBusMethodInvocation *context, @@ -2860,6 +2908,9 @@ case PROP_LOCATION: g_value_set_string (value, user->location); break; + case PROP_X_HAS_MESSAGES: + g_value_set_boolean (value, user->x_has_messages); + break; case PROP_X_KEYBOARD_LAYOUTS: g_value_set_boxed (value, g_strdupv (user->x_keyboard_layouts)); break; @@ -2935,6 +2986,7 @@ iface->handle_set_real_name = user_set_real_name; iface->handle_set_shell = user_set_shell; iface->handle_set_user_name = user_set_user_name; + iface->handle_set_xhas_messages = user_set_xhas_messages; iface->handle_set_xkeyboard_layouts = user_set_xkeyboard_layouts; iface->handle_set_xsession = user_set_x_session; iface->get_uid = user_real_get_uid; @@ -2968,6 +3020,7 @@ user->account_type = ACCOUNT_TYPE_STANDARD; user->home_dir = NULL; user->shell = NULL; + user->x_has_messages = FALSE; user->x_keyboard_layouts = NULL; user->background_file = NULL; user->icon_file = NULL; debian/patches/0011-add-background-file-support.patch0000664000000000000000000003142312240704731017516 0ustar Index: accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml =================================================================== --- accountsservice-0.6.35.orig/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:16:55.696125419 +0100 +++ accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:16:55.684125418 +0100 @@ -331,6 +331,41 @@ + + + + + + The absolute filename of a png file to use as the users background. + + + + + + + Sets the users background. + + + + The caller needs one of the following PolicyKit authorizations: + + + org.freedesktop.accounts.change-own-user-data + To change his own background + + + org.freedesktop.accounts.user-administration + To change the background of another user + + + + + if the caller lacks the appropriate PolicyKit authorization + if the operation failed + + + + @@ -723,6 +758,16 @@ + + + + + + + The filename of a png file containing the users background. + + + Index: accountsservice-0.6.35/src/libaccountsservice/act-user.c =================================================================== --- accountsservice-0.6.35.orig/src/libaccountsservice/act-user.c 2013-11-13 15:16:55.696125419 +0100 +++ accountsservice-0.6.35/src/libaccountsservice/act-user.c 2013-11-13 15:16:55.688125418 +0100 @@ -91,6 +91,7 @@ PROP_LOGIN_FREQUENCY, PROP_LOGIN_TIME, PROP_LOGIN_HISTORY, + PROP_BACKGROUND_FILE, PROP_ICON_FILE, PROP_LANGUAGE, PROP_FORMATS_LOCALE, @@ -121,6 +122,7 @@ char *shell; char *email; char *location; + char *background_file; char *icon_file; char *language; char *formats_locale; @@ -304,6 +306,9 @@ case PROP_LOCATION: g_value_set_string (value, user->location); break; + case PROP_BACKGROUND_FILE: + g_value_set_string (value, user->background_file); + break; case PROP_ICON_FILE: g_value_set_string (value, user->icon_file); break; @@ -455,6 +460,13 @@ NULL, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, + PROP_BACKGROUND_FILE, + g_param_spec_string ("background-file", + "Background File", + "The path to a background for this user.", + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, PROP_ICON_FILE, g_param_spec_string ("icon-file", "Icon File", @@ -585,6 +597,7 @@ g_free (user->user_name); g_free (user->real_name); + g_free (user->background_file); g_free (user->icon_file); g_free (user->language); g_free (user->object_path); @@ -1033,6 +1046,22 @@ } /** + * act_user_get_background_file: + * @user: a #ActUser + * + * Returns the path to the account background belonging to @user. + * + * Returns: (transfer none): a path to a background + */ +const char * +act_user_get_background_file (ActUser *user) +{ + g_return_val_if_fail (ACT_IS_USER (user), NULL); + + return user->background_file; +} + +/** * act_user_get_icon_file: * @user: a #ActUser * @@ -1290,6 +1319,15 @@ user->login_history = g_variant_ref (new_login_history); g_object_notify (G_OBJECT (user), "login-history"); } + } else if (strcmp (key, "BackgroundFile") == 0) { + const char *new_background_file; + + new_background_file = g_variant_get_string (value, NULL); + if (g_strcmp0 (user->background_file, new_background_file) != 0) { + g_free (user->background_file); + user->background_file = g_strdup (new_background_file); + g_object_notify (G_OBJECT (user), "background-file"); + } } else if (strcmp (key, "IconFile") == 0) { const char *new_icon_file; @@ -1760,6 +1798,35 @@ g_error_free (error); return; } +} + +/** + * act_user_set_background_file: + * @user: the user object to alter. + * @background_file: path to an background + * + * Assigns a new background for @user. + * + * Note this function is synchronous and ignores errors. + **/ +void +act_user_set_background_file (ActUser *user, + const char *background_file) +{ + GError *error = NULL; + + g_return_if_fail (ACT_IS_USER (user)); + g_return_if_fail (background_file != NULL); + g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy)); + + if (!accounts_user_call_set_background_file_sync (user->accounts_proxy, + background_file, + NULL, + &error)) { + g_warning ("SetBackgroundFile call failed: %s", error->message); + g_error_free (error); + return; + } } /** Index: accountsservice-0.6.35/src/user.c =================================================================== --- accountsservice-0.6.35.orig/src/user.c 2013-11-13 15:16:55.696125419 +0100 +++ accountsservice-0.6.35/src/user.c 2013-11-13 15:16:55.692125419 +0100 @@ -64,6 +64,7 @@ PROP_LOGIN_FREQUENCY, PROP_LOGIN_TIME, PROP_LOGIN_HISTORY, + PROP_BACKGROUND_FILE, PROP_ICON_FILE, PROP_LOCKED, PROP_PASSWORD_MODE, @@ -98,6 +99,7 @@ gchar *x_session; gchar *location; guint64 login_frequency; + gchar *background_file; gint64 login_time; GVariant *login_history; gchar *icon_file; @@ -369,6 +371,13 @@ g_object_notify (G_OBJECT (user), "password-hint"); } + s = g_key_file_get_string (keyfile, "User", "Background", NULL); + if (s != NULL) { + g_free (user->background_file); + user->background_file = s; + g_object_notify (G_OBJECT (user), "background-file"); + } + s = g_key_file_get_string (keyfile, "User", "Icon", NULL); if (s != NULL) { g_free (user->icon_file); @@ -436,6 +445,9 @@ if (user->password_hint) g_key_file_set_string (keyfile, "User", "PasswordHint", user->password_hint); + if (user->background_file) + g_key_file_set_string (keyfile, "User", "Background", user->background_file); + if (user->icon_file) g_key_file_set_string (keyfile, "User", "Icon", user->icon_file); @@ -1788,6 +1800,86 @@ } static void +user_change_background_file_authorized_cb (Daemon *daemon, + User *user, + GDBusMethodInvocation *context, + gpointer data) +{ + gchar *filename; + GFile *file; + GFileInfo *info; + GFileType type; + + filename = g_strdup (data); + + if (filename == NULL || + *filename == '\0') { + g_free (filename); + filename = NULL; + + goto background_saved; + } + + file = g_file_new_for_path (filename); + info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, + 0, NULL, NULL); + type = g_file_info_get_file_type (info); + + g_object_unref (info); + g_object_unref (file); + + if (type != G_FILE_TYPE_REGULAR) { + g_debug ("not a regular file\n"); + throw_error (context, ERROR_FAILED, "file '%s' is not a regular file", filename); + g_free (filename); + return; + } + +background_saved: + g_free (user->background_file); + user->background_file = filename; + + save_extra_data (user); + + accounts_user_emit_changed (ACCOUNTS_USER (user)); + + g_object_notify (G_OBJECT (user), "background-file"); + + accounts_user_complete_set_background_file (ACCOUNTS_USER (user), context); +} + +gboolean +user_set_background_file (AccountsUser *auser, + GDBusMethodInvocation *context, + const gchar *filename) +{ + User *user = (User*)auser; + int uid; + const gchar *action_id; + + if (!get_caller_uid (context, &uid)) { + throw_error (context, ERROR_FAILED, "identifying caller failed"); + return FALSE; + } + + if (user->uid == (uid_t) uid) + action_id = "org.freedesktop.accounts.change-own-user-data"; + else + action_id = "org.freedesktop.accounts.user-administration"; + + daemon_local_check_auth (user->daemon, + user, + action_id, + TRUE, + user_change_background_file_authorized_cb, + context, + g_strdup (filename), + (GDestroyNotify)g_free); + + return TRUE; +} + +static void user_change_icon_file_authorized_cb (Daemon *daemon, User *user, GDBusMethodInvocation *context, @@ -2590,6 +2682,7 @@ g_free (user->shell); g_free (user->icon_file); g_free (user->default_icon_file); + g_free (user->background_file); g_free (user->email); g_free (user->language); g_free (user->formats_locale); @@ -2705,6 +2798,9 @@ case PROP_LOCATION: g_value_set_string (value, user->location); break; + case PROP_BACKGROUND_FILE: + g_value_set_string (value, user->background_file); + break; case PROP_ICON_FILE: if (user->icon_file) g_value_set_string (value, user->icon_file); @@ -2761,6 +2857,7 @@ { iface->handle_set_account_type = user_set_account_type; iface->handle_set_automatic_login = user_set_automatic_login; + iface->handle_set_background_file = user_set_background_file; iface->handle_set_email = user_set_email; iface->handle_set_formats_locale = user_set_formats_locale; iface->handle_set_home_directory = user_set_home_directory; @@ -2805,6 +2902,7 @@ user->account_type = ACCOUNT_TYPE_STANDARD; user->home_dir = NULL; user->shell = NULL; + user->background_file = NULL; user->icon_file = NULL; user->default_icon_file = NULL; user->email = NULL; debian/patches/0002-create-and-manage-groups-like-on-a-debian-system.patch0000664000000000000000000001451112240704573023307 0ustar From: Frederic Peters Bug-Debian: http://bugs.debian.org/618764 Forwarded: not-needed Description: Create and manage groups like on a debian system. --- src/daemon.c | 22 ++++++---------------- src/user.c | 22 +++++++++++----------- src/util.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/util.h | 9 +++++++++ 4 files changed, 68 insertions(+), 27 deletions(-) --- accountsservice.orig/src/daemon.c +++ accountsservice/src/daemon.c @@ -1114,22 +1114,8 @@ daemon_create_user_authorized_cb (Daemon argv[1] = "-m"; argv[2] = "-c"; argv[3] = cd->real_name; - if (cd->account_type == ACCOUNT_TYPE_ADMINISTRATOR) { - argv[4] = "-G"; - argv[5] = "wheel"; - argv[6] = "--"; - argv[7] = cd->user_name; - argv[8] = NULL; - } - else if (cd->account_type == ACCOUNT_TYPE_STANDARD) { - argv[4] = "--"; - argv[5] = cd->user_name; - argv[6] = NULL; - } - else { - throw_error (context, ERROR_FAILED, "Don't know how to add user of type %d", cd->account_type); - return; - } + argv[4] = cd->user_name; + argv[5] = NULL; error = NULL; if (!spawn_with_login_uid (context, argv, &error)) { @@ -1138,6 +1124,10 @@ daemon_create_user_authorized_cb (Daemon return; } + if (cd->account_type == ACCOUNT_TYPE_ADMINISTRATOR) { + add_user_to_group (context, cd->user_name, "sudo"); + } + user = daemon_local_find_user_by_name (daemon, cd->user_name); user_update_local_account_property (user, TRUE); --- accountsservice.orig/src/user.c +++ accountsservice/src/user.c @@ -115,7 +115,7 @@ static gint account_type_from_pwent (struct passwd *pwent) { struct group *grp; - gid_t wheel; + gid_t admin; gid_t *groups; gint ngroups; gint i; @@ -125,17 +125,17 @@ account_type_from_pwent (struct passwd * return ACCOUNT_TYPE_ADMINISTRATOR; } - grp = getgrnam ("wheel"); + grp = getgrnam ("sudo"); if (grp == NULL) { - g_debug ("wheel group not found"); + g_debug ("sudo group not found"); return ACCOUNT_TYPE_STANDARD; } - wheel = grp->gr_gid; + admin = grp->gr_gid; ngroups = get_user_groups (pwent->pw_name, pwent->pw_gid, &groups); for (i = 0; i < ngroups; i++) { - if (groups[i] == wheel) { + if (groups[i] == admin) { g_free (groups); return ACCOUNT_TYPE_ADMINISTRATOR; } @@ -1281,7 +1281,7 @@ user_change_account_type_authorized_cb ( gid_t *groups; gint ngroups; GString *str; - gid_t wheel; + gid_t admin; struct group *grp; gint i; const gchar *argv[6]; @@ -1291,24 +1291,24 @@ user_change_account_type_authorized_cb ( "change account type of user '%s' (%d) to %d", user->user_name, user->uid, account_type); - grp = getgrnam ("wheel"); + grp = getgrnam ("sudo"); if (grp == NULL) { - throw_error (context, ERROR_FAILED, "failed to set account type: wheel group not found"); + throw_error (context, ERROR_FAILED, "failed to set account type: sudo group not found"); return; } - wheel = grp->gr_gid; + admin = grp->gr_gid; ngroups = get_user_groups (user->user_name, user->gid, &groups); str = g_string_new (""); for (i = 0; i < ngroups; i++) { - if (groups[i] == wheel) + if (groups[i] == admin) continue; g_string_append_printf (str, "%d,", groups[i]); } switch (account_type) { case ACCOUNT_TYPE_ADMINISTRATOR: - g_string_append_printf (str, "%d", wheel); + g_string_append_printf (str, "%d", admin); break; case ACCOUNT_TYPE_STANDARD: default: --- accountsservice.orig/src/util.c +++ accountsservice/src/util.c @@ -302,3 +302,45 @@ get_caller_uid (GDBusMethodInvocation *c return TRUE; } + +void +add_user_to_group (GDBusMethodInvocation *context, + const char *user_name, + const char *group_name) +{ + GError *error; + gchar *argv[4]; + + argv[0] = (gchar*) "/usr/sbin/adduser"; + argv[1] = (gchar*) user_name; + argv[2] = (gchar*) group_name; + argv[3] = NULL; + + error = NULL; + if (!spawn_with_login_uid (context, argv, &error)) { + g_warning ("failed to add user %s to group %s", user_name, group_name); + g_error_free (error); + return; + } +} + +void +remove_user_from_group (GDBusMethodInvocation *context, + const char *user_name, + const char *group_name) +{ + GError *error; + gchar *argv[4]; + + argv[0] = (gchar*) "/usr/sbin/deluser"; + argv[1] = (gchar*) user_name; + argv[2] = (gchar*) group_name; + argv[3] = NULL; + + error = NULL; + if (!spawn_with_login_uid (context, argv, &error)) { + g_warning ("failed to remove user %s from group %s", user_name, group_name); + g_error_free (error); + return; + } +} --- accountsservice.orig/src/util.h +++ accountsservice/src/util.h @@ -40,6 +40,15 @@ gint get_user_groups (const gchar *user gid_t group, gid_t **groups); +void add_user_to_group (GDBusMethodInvocation *context, + const char *user_name, + const char *group_name); + +void remove_user_from_group (GDBusMethodInvocation *context, + const char *user_name, + const char *group_name); + + G_END_DECLS #endif /* __UTIL_H__ */ debian/patches/0008-nopasswdlogin-group.patch0000664000000000000000000000624712240704720016255 0ustar --- src/user.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) Index: accountsservice-0.6.35/src/user.c =================================================================== --- accountsservice-0.6.35.orig/src/user.c 2013-11-13 15:16:46.892125154 +0100 +++ accountsservice-0.6.35/src/user.c 2013-11-13 15:16:46.888125154 +0100 @@ -1824,6 +1824,21 @@ return; } + if (mode == PASSWORD_MODE_NONE) { + argv[0] = "/usr/bin/gpasswd"; + argv[1] = "-a"; + argv[2] = user->user_name; + argv[3] = "nopasswdlogin"; + argv[4] = NULL; + + error = NULL; + if (!spawn_with_login_uid (context, argv, &error)) { + throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); + g_error_free (error); + return; + } + } + if (mode == PASSWORD_MODE_SET_AT_LOGIN) { argv[0] = "/usr/bin/chage"; argv[1] = "-d"; @@ -1871,6 +1886,23 @@ g_object_notify (G_OBJECT (user), "locked"); } + /* Remember to remove user from nopasswdlogin group if we're + switching away from no-password mode */ + if (user->password_mode == PASSWORD_MODE_NONE) { + argv[0] = "/usr/bin/gpasswd"; + argv[1] = "-d"; + argv[2] = user->user_name; + argv[3] = "nopasswdlogin"; + argv[4] = NULL; + + error = NULL; + if (!spawn_with_login_uid (context, argv, &error)) { + throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); + g_error_free (error); + return; + } + } + user->password_mode = mode; g_object_notify (G_OBJECT (user), "password-mode"); @@ -1938,6 +1970,20 @@ error = NULL; if (!spawn_with_login_uid (context, argv, &error)) { + throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); + g_error_free (error); + return; + } + + /* Drop user from nopasswdlogin group */ + argv[0] = "/usr/bin/gpasswd"; + argv[1] = "-d"; + argv[2] = user->user_name; + argv[3] = "nopasswdlogin"; + argv[4] = NULL; + + error = NULL; + if (!spawn_with_login_uid (context, argv, &error)) { throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); g_error_free (error); return; debian/patches/0015-pam-pin-ubuntu.patch0000664000000000000000000002601212240705406015105 0ustar Author: Michael Terry Description: Ubuntu integration tweaks to PAM PIN module * Switch PAM stack name password-auth (Fedora) to common-password (Debian) * Check legacy location /var/lib/dbus/machine-id for machine ID * Use gnutls to initialize gcrypt for us, because other PAM modules will try to initialize gnutls, and we need to all initialize gcrypt the same way (it will ignore future attempts to configure it once configured) * Add back SetPassword to the interface, to avoid dropping symbols. Note that I additionally changed SetPassword to clear any existing PIN. Index: accountsservice-0.6.35/data/accountsservice =================================================================== --- accountsservice-0.6.35.orig/data/accountsservice 2013-11-13 15:21:56.256134468 +0100 +++ accountsservice-0.6.35/data/accountsservice 2013-11-13 15:21:56.244134468 +0100 @@ -1,6 +1,6 @@ #%PAM-1.0 # Must use substack here, so the success of pam_unix will still # cause our pam_pin to run -password substack password-auth +password substack common-password password optional pam_pin.so Index: accountsservice-0.6.35/src/pam-pin/pam-module.c =================================================================== --- accountsservice-0.6.35.orig/src/pam-pin/pam-module.c 2013-11-13 15:21:56.256134468 +0100 +++ accountsservice-0.6.35/src/pam-pin/pam-module.c 2013-11-13 15:21:56.248134468 +0100 @@ -33,6 +33,7 @@ #include #include #include +#include /* We use AES256 in Cipher Block Chaining mode, using a key derived from the PIN, salted with the machine id @@ -44,8 +45,11 @@ static void init_libgcrypt (void) { - /* Despite the name, this is a library init function... */ - gcry_check_version (GCRYPT_VERSION); + /* gnutls_global_init () will initialize gcrypt for us a certain way. + We initialize gnutls instead of gcrypt because other pam modules + (ldap) may use gnutls and we need to initialize gcrypt the same way. + */ + gnutls_global_init (); } static char * @@ -56,6 +60,8 @@ size_t machine_id_len; if (!g_file_get_contents ("/etc/machine-id", &machine_id, + &machine_id_len, NULL) && + !g_file_get_contents ("/var/lib/dbus/machine-id", &machine_id, &machine_id_len, NULL)) return NULL; Index: accountsservice-0.6.35/configure.ac =================================================================== --- accountsservice-0.6.35.orig/configure.ac 2013-11-13 15:21:56.256134468 +0100 +++ accountsservice-0.6.35/configure.ac 2013-11-13 15:21:56.248134468 +0100 @@ -292,6 +292,9 @@ [enable_pin_authentication=yes]) if test x$enable_pin_autentication != xno ; then AM_PATH_LIBGCRYPT + PKG_CHECK_MODULES(LIBGNUTLS, gnutls, + [enable_pin_authentication=yes], + [enable_pin_authentication=no]) fi AM_CONDITIONAL(HAVE_PAM_MODULE, [test x$enable_pin_authentication != xno]) Index: accountsservice-0.6.35/src/pam-pin/Makefile.am =================================================================== --- accountsservice-0.6.35.orig/src/pam-pin/Makefile.am 2013-11-13 15:21:56.256134468 +0100 +++ accountsservice-0.6.35/src/pam-pin/Makefile.am 2013-11-13 15:21:56.248134468 +0100 @@ -4,13 +4,14 @@ pam_pin_la_SOURCES = pam-module.c pam_pin_la_LDFLAGS = -module -avoid-version -pam_pin_la_LIBADD = $(LIBGCRYPT_LIBS) $(GIO_LIBS) +pam_pin_la_LIBADD = $(LIBGNUTLS_LIBS) $(LIBGCRYPT_LIBS) $(GIO_LIBS) pam_pin_la_CFLAGS = \ -DLOCALSTATEDIR=\""$(localstatedir)"\" \ -DDATADIR=\""$(datadir)"\" \ -DUSERDIR=\"$(localstatedir)/lib/AccountsService/users\" \ -DPASSWDDIR=\"$(localstatedir)/lib/AccountsService/encrypted-password\" \ -DLIBEXECDIR=\"$(libexecdir)\" \ + $(LIBGNUTLS_CFLAGS) \ $(LIBGCRYPT_CFLAGS) \ $(GIO_CFLAGS) \ $(WARN_CFLAGS) Index: accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml =================================================================== --- accountsservice-0.6.35.orig/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:21:56.256134468 +0100 +++ accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:21:56.248134468 +0100 @@ -595,6 +595,49 @@ + + + + + + The crypted password. + + + + + + + The password hint. + + + + + + + Sets a new password for this user. + + + Note that setting a password has the side-effect of + unlocking the account. You cannot set a PIN with + this method. + + + + The caller needs one of the following PolicyKit authorizations: + + + org.freedesktop.accounts.user-administration + To change the password of a user + + + + + if the caller lacks the appropriate PolicyKit authorization + if the operation failed + + + + Index: accountsservice-0.6.35/src/user.c =================================================================== --- accountsservice-0.6.35.orig/src/user.c 2013-11-13 15:21:56.256134468 +0100 +++ accountsservice-0.6.35/src/user.c 2013-11-13 15:21:56.252134468 +0100 @@ -29,6 +29,7 @@ #include #include #include +#include #include #ifdef HAVE_SHADOW_H #include @@ -2535,6 +2536,122 @@ } static void +user_change_password_authorized_cb (Daemon *daemon, + User *user, + GDBusMethodInvocation *context, + gpointer data) + +{ + gchar **strings = data; + GError *error; + const gchar *argv[6]; + gchar *pin_filename; + + sys_log (context, + "set password and hint of user '%s' (%d)", + user->user_name, user->uid); + + g_object_freeze_notify (G_OBJECT (user)); + + argv[0] = "/usr/sbin/usermod"; + argv[1] = "-p"; + argv[2] = strings[0]; + argv[3] = "--"; + argv[4] = user->user_name; + argv[5] = NULL; + + error = NULL; + if (!spawn_with_login_uid (context, argv, &error)) { + throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); + g_error_free (error); + return; + } + + /* Drop user from nopasswdlogin group */ + argv[0] = "/usr/bin/gpasswd"; + argv[1] = "-d"; + argv[2] = user->user_name; + argv[3] = "nopasswdlogin"; + argv[4] = NULL; + + error = NULL; + if (!spawn_with_login_uid (context, argv, &error)) { + /* It is OK for this to fail, it will do so if the user isn't + in the group, which is a valid situation. + throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); + g_error_free (error); + return; + */ + } + + /* Make sure to delete PIN file too, to erase any PIN. If we ended up + in this function, the user interacted with an interface that did not + offer a PIN entry. */ + pin_filename = g_build_filename (PASSWDDIR, user->user_name, NULL); + g_unlink (pin_filename); + g_free (pin_filename); + + if (user->password_mode != PASSWORD_MODE_REGULAR) { + user->password_mode = PASSWORD_MODE_REGULAR; + g_object_notify (G_OBJECT (user), "password-mode"); + } + + if (user->locked) { + user->locked = FALSE; + g_object_notify (G_OBJECT (user), "locked"); + } + + if (g_strcmp0 (user->password_hint, strings[1]) != 0) { + g_free (user->password_hint); + user->password_hint = g_strdup (strings[1]); + g_object_notify (G_OBJECT (user), "password-hint"); + } + + save_extra_data (user); + + g_object_thaw_notify (G_OBJECT (user)); + + accounts_user_emit_changed (ACCOUNTS_USER (user)); + + accounts_user_complete_set_password (ACCOUNTS_USER (user), context); +} + +static void +free_passwords (gchar **strings) +{ + memset (strings[0], 0, strlen (strings[0])); + g_strfreev (strings); +} + +static gboolean +user_set_password (AccountsUser *auser, + GDBusMethodInvocation *context, + const gchar *password, + const gchar *hint) +{ + User *user = (User*)auser; + gchar **data; + + data = g_new (gchar *, 3); + data[0] = g_strdup (password); + data[1] = g_strdup (hint); + data[2] = NULL; + + daemon_local_check_auth (user->daemon, + user, + "org.freedesktop.accounts.user-administration", + TRUE, + user_change_password_authorized_cb, + context, + data, + (GDestroyNotify)free_passwords); + + memset ((char*)password, 0, strlen (password)); + + return TRUE; +} + +static void user_continue_change_password_authorized_cb (Daemon *daemon, User *user, GDBusMethodInvocation *context, Index: accountsservice-0.6.35/src/Makefile.am =================================================================== --- accountsservice-0.6.35.orig/src/Makefile.am 2013-11-13 15:21:56.256134468 +0100 +++ accountsservice-0.6.35/src/Makefile.am 2013-11-13 15:21:56.252134468 +0100 @@ -11,6 +11,7 @@ -DDATADIR=\""$(datadir)"\" \ -DICONDIR=\"$(localstatedir)/lib/AccountsService/icons\" \ -DUSERDIR=\"$(localstatedir)/lib/AccountsService/users\" \ + -DPASSWDDIR=\"$(localstatedir)/lib/AccountsService/encrypted-password\" \ -DLIBEXECDIR=\"$(libexecdir)\" \ -I$(srcdir) \ -I$(builddir) \ debian/patches/series0000664000000000000000000000102212252033736012032 0ustar 0001-formats-locale-property.patch 0002-create-and-manage-groups-like-on-a-ubuntu-system.patch #0005-gdm_config_file_path.patch 0006-adduser_instead_of_useradd.patch 0007-add-lightdm-support.patch 0008-nopasswdlogin-group.patch 0009-language-tools.patch 0010-set-language.patch 0011-add-background-file-support.patch 0012-add-keyboard-layout-support.patch 0013-add-has-message-support.patch 0014-pam-pin.patch 0015-pam-pin-ubuntu.patch 2002-disable_systemd.patch 0016-add-input-sources-support.patch 0017-clean-up-cache-dir.patch debian/patches/0009-language-tools.patch0000664000000000000000000003462112240704723015156 0ustar Description: Help files for dealing with language/locale settings. Author: Gunnar Hjalmarsson Index: accountsservice-0.6.35/configure.ac =================================================================== --- accountsservice-0.6.35.orig/configure.ac 2013-11-13 15:16:49.312125227 +0100 +++ accountsservice-0.6.35/configure.ac 2013-11-13 15:16:49.300125226 +0100 @@ -286,6 +286,7 @@ Makefile po/Makefile.in data/Makefile +data/langtools/Makefile src/Makefile src/libaccountsservice/Makefile src/libaccountsservice/accountsservice.pc Index: accountsservice-0.6.35/data/langtools/language2locale =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.35/data/langtools/language2locale 2013-11-13 15:16:49.300125226 +0100 @@ -0,0 +1,65 @@ +#!/bin/sh -e +# +# - takes the first choice language in the LANGUAGE priority list as argument +# - outputs locale name corresponding to that language + +lang=$1 +locale_name= + +test -n "$lang" || exit 1 + +langtoolsdir=/usr/share/language-tools + +langcode=${lang%%[_@]*} +locales= +for loc in $( locale -a | grep -F .utf8 ); do + # skip locales for other languages + if [ $langcode = ${loc%%[._@]*} ]; then + loc=${loc%.*}${loc#*.utf8} + locales="$locales $loc" + fi +done + +# exact match +for loc in $locales; do + if [ $lang = $loc ]; then + locale_name=$( echo $loc | sed -r 's/([^@]+)/\1.UTF-8/' ) + break + fi +done + +if [ -z "$locale_name" -a $lang = ${lang%_[A-Z]*} ]; then + + # try the "main" country code if any + main_country= + while read line; do + if [ "${line%%[[:space:]]*}" = $langcode ]; then + main_country=${line##*[[:space:]]} + if [ $lang != ${lang#*@} ]; then + main_country=$main_country@${lang#*@} + fi + break + fi + done < $langtoolsdir/main-countries + if [ -n "$main_country" ]; then + for loc in $locales; do + if [ $main_country = $loc ]; then + locale_name=$( echo $loc | sed -r 's/([^@]+)/\1.UTF-8/' ) + break + fi + done + fi + + # try out fitting locale with any country code + if [ -z "$locale_name" -a $langcode != 'zh' ]; then + for loc in $locales; do + if [ "${loc%%[_@]*}" = $langcode ]; then + locale_name=$( echo $loc | sed -r 's/([^@]+)/\1.UTF-8/' ) + break + fi + done + fi +fi + +echo $locale_name + Index: accountsservice-0.6.35/data/langtools/language-options =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.35/data/langtools/language-options 2013-11-13 15:16:49.300125226 +0100 @@ -0,0 +1,79 @@ +#!/usr/bin/perl +use strict; +use warnings; + +my $langtoolsdir = '/usr/share/language-tools'; + +# get the locales available on the system +my @avail_locales = map { chomp; s/\.utf8//; $_ } qx( locale -a | grep -F .utf8 ); + +# add items without country code to facilitate lookups +my %extended_localelist; +for my $loc (@avail_locales) { + ( my $lang = $loc ) =~ s/_[A-Z]+//; + @extended_localelist{$loc, $lang} = (1, 1); +} + +# get the directory names in /usr/share/locale-langpack plus possible other +# translation directory names in /usr/share/locale and /usr/local/share/locale +my %translation_dirs; +if ( opendir my ($dh), '/usr/share/locale-langpack' ) { + $translation_dirs{$_} = 1 for readdir $dh; +} +my %langpack_langcodes = map { s/[^a-z].+//; $_, 1 } + grep !/^\./, keys %translation_dirs; +for my $t_dir ('/usr/share/locale', '/usr/local/share/locale') { + if ( opendir my ($dh), $t_dir ) { + for ( readdir $dh ) { + for my $lang ( keys %langpack_langcodes ) { + if ( /^$lang[_@]/ ) { + $translation_dirs{$_} = 1; + last; + } + } + } + } +} + +# get the intersection of available translation_dirs and the extended locale list +my %intersection; +for ( keys %extended_localelist ) { + $intersection{$_} = 1 if $translation_dirs{$_}; +} + +# adjustments +if ( open my $fh, '<', "$langtoolsdir/main-countries" ) { + # If country code items in a language exist: + # - Remove the item without country code, since gettext won't find a + # translation under e.g. 'de_DE' if the first item in LANGUAGE is 'de' + # (see https://launchpad.net/bugs/700213). 'en' is kept, though, since + # it's always the last item in LANGUAGE per design. + # - Make sure that the main dialect of the language is represented among + # the country code items (see https://launchpad.net/bugs/710148). + my %main; + while ( <$fh> ) { + next if /^\s*(?:#|$)/; + my ($k, $v) = split; + $main{$k} = $v; + } + my %count; + for ( keys %intersection ) { + next if /^en[^a-z]/; + ( my $not_country = $_ ) =~ s/_[A-Z]+//; + $count{$not_country} ++; + } + for my $langcode ( keys %count ) { + if ( $count{$langcode} > 1 ) { + delete $intersection{$langcode}; + $intersection{ $main{$langcode} } = 1 if $main{$langcode}; + } + } +} else { + # not access to the language-to-main-dialect map + # => stick with a minimum of list manipulation + delete $intersection{'zh'}; +} + +# print the resulting list of language options +print join("\n", sort keys %intersection) || 'en'; + Index: accountsservice-0.6.35/data/langtools/language-validate =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.35/data/langtools/language-validate 2013-11-13 15:16:49.304125226 +0100 @@ -0,0 +1,78 @@ +#!/bin/sh -e + +lang=$1 +validated_language= + +test -n "$lang" || exit 1 + +langtoolsdir=/usr/share/language-tools + +# +# discard possible fallback languages +# +lang=${lang%%:*} + +# +# remove possible encoding part +# +if [ $lang != ${lang%.utf8*} ]; then + lang=${lang%.*}${lang#*.utf8} +elif [ $lang != ${lang%.UTF-8*} ]; then + lang=${lang%.*}${lang#*.UTF-8} +fi + +# +# make sure that the output is a valid language option +# +options=$( $langtoolsdir/language-options ) + +# exact match +for opt in $options; do + if [ $opt = $lang ]; then + validated_language=$lang + break + fi +done + +if [ -z "$validated_language" ]; then + langcode=${lang%%[_@]*} + + # try the "main" country code if any + main_country= + while read line; do + if [ "${line%%[[:space:]]*}" = $langcode ]; then + main_country=${line##*[[:space:]]} + if [ $lang != ${lang#*@} ]; then + main_country=$main_country@${lang#*@} + is_variant=true + fi + break + fi + done < $langtoolsdir/main-countries + if [ -n "$main_country" ]; then + for opt in $options; do + if [ $main_country = $opt ]; then + validated_language=$main_country + break + fi + done + fi + + # try out fitting language option without paying regard to + # country code or variant + if [ -z "$validated_language" ]; then + for opt in $options; do + if [ "${opt%%[_@]*}" = $langcode -a $langcode != 'zh' ]; then + validated_language=$opt + break + fi + done + fi +fi + +if [ -z "$validated_language" ]; then + validated_language='en' +fi + +echo $validated_language + Index: accountsservice-0.6.35/data/langtools/locale2papersize =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.35/data/langtools/locale2papersize 2013-11-13 15:16:49.304125226 +0100 @@ -0,0 +1,18 @@ +#!/bin/sh -e +# +# locale2papersize outputs the paper size "a4" or "letter" based on +# the height and width in the locale that is passed as an argument. + +export LC_PAPER=$1 + +height=$( locale height ) +width=$( locale width ) + +if [ "$height" = 279 -a "$width" = 216 ]; then + size=letter +else + size=a4 +fi + +echo $size + Index: accountsservice-0.6.35/data/langtools/main-countries =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.35/data/langtools/main-countries 2013-11-13 15:16:49.304125226 +0100 @@ -0,0 +1,28 @@ +# If multiple country codes are present among the available locales for +# a language, we may want to map the language code to the language's +# main or origin country. The list below aims to serve that purpose. +# +aa aa_ET +ar ar_EG +bn bn_BD +ca ca_ES +de de_DE +el el_GR +en en_US +es es_ES +eu eu_ES +fr fr_FR +fy fy_NL +it it_IT +li li_NL +nl nl_NL +om om_ET +pa pa_PK +pt pt_PT +ru ru_RU +so so_SO +sr sr_RS +sv sv_SE +ti ti_ER +tr tr_TR + Index: accountsservice-0.6.35/data/langtools/Makefile.am =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.35/data/langtools/Makefile.am 2013-11-13 15:16:49.304125226 +0100 @@ -0,0 +1,17 @@ +langtoolsdir = ${datadir}/language-tools + +install-data-hook: + if test '!' -d $(DESTDIR)$(langtoolsdir); then \ + $(mkinstalldirs) $(DESTDIR)$(langtoolsdir); \ + chmod 755 $(DESTDIR)$(langtoolsdir); \ + fi + + $(INSTALL_SCRIPT) language-options $(DESTDIR)$(langtoolsdir)/language-options + $(INSTALL_SCRIPT) language-validate $(DESTDIR)$(langtoolsdir)/language-validate + $(INSTALL_SCRIPT) language2locale $(DESTDIR)$(langtoolsdir)/language2locale + $(INSTALL_SCRIPT) locale2papersize $(DESTDIR)$(langtoolsdir)/locale2papersize + $(INSTALL_DATA) main-countries $(DESTDIR)$(langtoolsdir)/main-countries + $(INSTALL_SCRIPT) save-to-pam-env $(DESTDIR)$(langtoolsdir)/save-to-pam-env + $(INSTALL_SCRIPT) set-language-helper $(DESTDIR)$(langtoolsdir)/set-language-helper + $(INSTALL_SCRIPT) update-langlist $(DESTDIR)$(langtoolsdir)/update-langlist + Index: accountsservice-0.6.35/data/langtools/save-to-pam-env =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.35/data/langtools/save-to-pam-env 2013-11-13 15:16:49.304125226 +0100 @@ -0,0 +1,40 @@ +#!/bin/sh -e +# +# updates the ~/.pam_environment config file + +homedir=$1 +locale_name=$2 +language_list=$3 + +[ -n "$homedir" -a -n "$locale_name" ] || exit 1 + +langtoolsdir=/usr/share/language-tools + +# create ~/.pam_environment if it doesn't exist +touch "$homedir/.pam_environment" || exit 1 + +save_to_pam_env() { + var=$1; value=$2 + if [ "$( grep "^$var=" .pam_environment )" ]; then + sed -r -i "s/^($var=).*/\1$value/" .pam_environment + else + echo "$var=$value" >> .pam_environment + fi +} + +cd "$homedir" +if [ -n "$language_list" ]; then + save_to_pam_env 'LANGUAGE' $language_list + save_to_pam_env 'LANG' $locale_name +else + for var in 'LC_NUMERIC' 'LC_TIME' 'LC_MONETARY' 'LC_PAPER' 'LC_NAME' \ + 'LC_ADDRESS' 'LC_TELEPHONE' 'LC_MEASUREMENT' 'LC_IDENTIFICATION'; do + save_to_pam_env $var $locale_name + done + papersize=$( $langtoolsdir/locale2papersize $locale_name ) + save_to_pam_env 'PAPERSIZE' $papersize + echo $locale_name +fi + +exit 0 + Index: accountsservice-0.6.35/data/langtools/set-language-helper =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.35/data/langtools/set-language-helper 2013-11-13 15:16:49.304125226 +0100 @@ -0,0 +1,27 @@ +#!/bin/sh -e + +homedir=$1 +language=$2 +validated_language= + +[ -n "$language" -a -n "$homedir" ] || exit 1 + +langtoolsdir=/usr/share/language-tools + +validated_language=$( $langtoolsdir/language-validate $language ) + +if ! dpkg -l language-selector-gnome > /dev/null 2>&1; then + renewed_langlist=$validated_language +elif [ $language = "${language%:*}" ]; then + renewed_langlist=$( $langtoolsdir/update-langlist $validated_language "$homedir" ) +else + # $language contains a priority list + renewed_langlist=$validated_language:${language#*:} +fi + +locale_name=$( $langtoolsdir/language2locale $validated_language ) + +( $langtoolsdir/save-to-pam-env "$homedir" $locale_name $renewed_langlist ) || exit 1 + +echo $validated_language + Index: accountsservice-0.6.35/data/langtools/update-langlist =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.35/data/langtools/update-langlist 2013-11-13 15:16:49.304125226 +0100 @@ -0,0 +1,48 @@ +#!/bin/sh -e +# +# update-langlist maintains the LANGUAGE priority list. It does so in +# a simplified manner, unlike the UI in language-selector-gnome for +# setting the user language which provides full control. + +first_language=$1 +homedir=$2 +renewed_langlist= + +[ -n "$first_language" -a -n "$homedir" ] || exit 1 + +get_old_langlist() { + if [ -r "$homedir/.pam_environment" ]; then + while read line; do + if [ "${line%=*}" = 'LANGUAGE' ]; then + old_langlist=${line#*=} + break + fi + done < $homedir/.pam_environment + fi +} + +old_langlist= +english=true +if [ ${first_language%%[_@]*} != 'en' ]; then + get_old_langlist + english=false +fi + +if [ -n "$old_langlist" ] && ! $english; then + if expr $old_langlist : ".*:$first_language:" > /dev/null ; then + renewed_langlist=$( echo $old_langlist | sed -r "s/(.+:)($first_language:)/\2\1/" ) + elif [ ${old_langlist%%:*} = $first_language ]; then + # no change + renewed_langlist=$old_langlist + else + renewed_langlist=$first_language:$old_langlist + fi +else + # build fresh list with 'en' as the last element + # no other languages needed if English was selected + renewed_langlist=$first_language + [ $first_language != 'en' ] && renewed_langlist=$renewed_langlist:en +fi + +echo $renewed_langlist + Index: accountsservice-0.6.35/data/Makefile.am =================================================================== --- accountsservice-0.6.35.orig/data/Makefile.am 2013-11-13 15:16:49.312125227 +0100 +++ accountsservice-0.6.35/data/Makefile.am 2013-11-13 15:16:49.304125226 +0100 @@ -1,3 +1,4 @@ +SUBDIRS = langtools dbusifdir = $(datadir)/dbus-1/interfaces dbusif_DATA = \ debian/patches/git_hold_keyfiles.patch0000664000000000000000000000761212240704573015336 0ustar 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 (); } debian/patches/2002-disable_systemd.patch0000664000000000000000000000131612240704573015401 0ustar Description: Remove SystemdService from DBus service file. Author: Alessio Treglia Bug-Debian: http://bugs.debian.org/675925 --- data/org.freedesktop.Accounts.service.in | 1 - 1 file changed, 1 deletion(-) Index: accountsservice-0.6.34/data/org.freedesktop.Accounts.service.in =================================================================== --- accountsservice-0.6.34.orig/data/org.freedesktop.Accounts.service.in 2013-06-26 20:02:05.759804884 +0200 +++ accountsservice-0.6.34/data/org.freedesktop.Accounts.service.in 2013-06-26 20:02:05.751804883 +0200 @@ -2,4 +2,3 @@ Name=org.freedesktop.Accounts Exec=@libexecdir@/accounts-daemon User=root -SystemdService=accounts-daemon.service debian/patches/0006-adduser_instead_of_useradd.patch0000664000000000000000000000214712240704712017557 0ustar Author: Alessio Treglia Description: Replace useradd with adduser to comply with Debian Policy. Bug-Ubuntu: https://launchpad.net/bugs/810907 Forwarded: no --- src/daemon.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) Index: accountsservice-0.6.35/src/daemon.c =================================================================== --- accountsservice-0.6.35.orig/src/daemon.c 2013-11-13 15:16:41.340124986 +0100 +++ accountsservice-0.6.35/src/daemon.c 2013-11-13 15:16:41.332124986 +0100 @@ -1061,12 +1061,13 @@ sys_log (context, "create user '%s'", cd->user_name); - argv[0] = "/usr/sbin/useradd"; - argv[1] = "-m"; - argv[2] = "-c"; - argv[3] = cd->real_name; - argv[4] = cd->user_name; - argv[5] = NULL; + argv[0] = "/usr/sbin/adduser"; + argv[1] = "--quiet"; + argv[2] = "--disabled-login"; + argv[3] = "--gecos"; + argv[4] = cd->real_name; + argv[5] = cd->user_name; + argv[6] = NULL; error = NULL; if (!spawn_with_login_uid (context, argv, &error)) { debian/patches/0014-pam-pin.patch0000664000000000000000000014411112240705402013561 0ustar Author: Giovanni Campagna Description: Add PAM module for PIN codes This patch gathers six patches dated 2013-02-16 in the upstream bug. There are further Ubuntu tweaks in a second patch, separated to make it easier to update this patch from the upstream bug. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=51833 Index: accountsservice-0.6.35/data/Makefile.am =================================================================== --- accountsservice-0.6.35.orig/data/Makefile.am 2013-11-13 15:20:32.228131938 +0100 +++ accountsservice-0.6.35/data/Makefile.am 2013-11-13 15:20:32.208131938 +0100 @@ -19,6 +19,9 @@ policy_in_files = org.freedesktop.accounts.policy.in policy_DATA = $(policy_in_files:.policy.in=.policy) +pamdir = $(sysconfdir)/pam.d +dist_pam_DATA = accountsservice + @INTLTOOL_POLICY_RULE@ if HAVE_SYSTEMD Index: accountsservice-0.6.35/data/accountsservice =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.35/data/accountsservice 2013-11-13 15:20:32.208131938 +0100 @@ -0,0 +1,6 @@ +#%PAM-1.0 +# Must use substack here, so the success of pam_unix will still +# cause our pam_pin to run +password substack password-auth +password optional pam_pin.so + Index: accountsservice-0.6.35/src/Makefile.am =================================================================== --- accountsservice-0.6.35.orig/src/Makefile.am 2013-11-13 15:20:32.228131938 +0100 +++ accountsservice-0.6.35/src/Makefile.am 2013-11-13 15:21:48.484134234 +0100 @@ -1,14 +1,21 @@ NULL = BUILT_SOURCES = SUBDIRS = . libaccountsservice + +if HAVE_PAM_MODULE +SUBDIRS += pam-pin +endif + INCLUDES = \ -DLOCALSTATEDIR=\""$(localstatedir)"\" \ -DDATADIR=\""$(datadir)"\" \ -DICONDIR=\"$(localstatedir)/lib/AccountsService/icons\" \ -DUSERDIR=\"$(localstatedir)/lib/AccountsService/users\" \ + -DLIBEXECDIR=\"$(libexecdir)\" \ -I$(srcdir) \ -I$(builddir) \ $(POLKIT_CFLAGS) \ + $(GCR_CFLAGS) \ $(WARN_CFLAGS) noinst_LTLIBRARIES = libaccounts-generated.la @@ -27,7 +34,7 @@ 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 +libexec_PROGRAMS = accounts-daemon accounts-daemon-pam-password-helper accounts_daemon_SOURCES = \ $(enums_h_sources) \ @@ -45,8 +52,15 @@ accounts_daemon_LDADD = \ libaccounts-generated.la \ + $(GCR_LIBS) \ $(POLKIT_LIBS) +accounts_daemon_pam_password_helper_SOURCES = \ + pam-password-helper.c +accounts_daemon_pam_password_helper_LDADD = \ + $(GIO_LIBS) \ + -lpam + CLEANFILES = \ $(BUILT_SOURCES) \ *.gcda \ @@ -56,3 +70,7 @@ install-data-hook: $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/AccountsService/users" $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/AccountsService/icons" + +install-exec-hook: + -chown root $(DESTDIR)$(libexecdir)/accounts-daemon-pam-password-helper + -chmod 4755 $(DESTDIR)$(libexecdir)/accounts-daemon-pam-password-helper Index: accountsservice-0.6.35/src/libaccountsservice/act-user.c =================================================================== --- accountsservice-0.6.35.orig/src/libaccountsservice/act-user.c 2013-11-13 15:20:32.228131938 +0100 +++ accountsservice-0.6.35/src/libaccountsservice/act-user.c 2013-11-13 15:20:32.212131938 +0100 @@ -30,6 +30,9 @@ #include #include +#define GCR_API_SUBJECT_TO_CHANGE +#include + #include "act-user-private.h" #include "accounts-user-generated.h" @@ -2097,42 +2100,6 @@ } } -static gchar -salt_char (GRand *rand) -{ - gchar salt[] = "ABCDEFGHIJKLMNOPQRSTUVXYZ" - "abcdefghijklmnopqrstuvxyz" - "./0123456789"; - - return salt[g_rand_int_range (rand, 0, G_N_ELEMENTS (salt))]; -} - -static gchar * -make_crypted (const gchar *plain) -{ - GString *salt; - gchar *result; - GRand *rand; - gint i; - - rand = g_rand_new (); - salt = g_string_sized_new (21); - - /* SHA 256 */ - g_string_append (salt, "$6$"); - for (i = 0; i < 16; i++) { - g_string_append_c (salt, salt_char (rand)); - } - g_string_append_c (salt, '$'); - - result = g_strdup (crypt (plain, salt->str)); - - g_string_free (salt, TRUE); - g_rand_free (rand); - - return result; -} - /** * act_user_set_password: * @user: the user object to alter. @@ -2149,24 +2116,85 @@ const gchar *password, const gchar *hint) { - GError *error = NULL; - gchar *crypted; + GHashTable *table; g_return_if_fail (ACT_IS_USER (user)); g_return_if_fail (password != NULL); + + table = g_hash_table_new (g_direct_hash, g_direct_equal); + g_hash_table_insert (table, GINT_TO_POINTER (ACT_USER_PASSWORD_REGULAR), + (gpointer) password); + g_hash_table_insert (table, GINT_TO_POINTER (ACT_USER_PASSWORD_HINT), + (gpointer) hint); + + act_user_set_multiple_passwords (user, table); + + g_hash_table_unref (table); +} + +/** + * act_user_set_multiple_passwords: + * @user: the user object to alter. + * @password_map: (element-type guint utf8): a #GHashTable mapping + * #ActUserPasswordType to a plain-text password + * + * Changes password, password hint and PIN of @user, using the + * values taken from @password_map. + * + * Note this function is synchronous and ignores errors. + **/ +/* Note on the API: what we really want here is a list of (int-string) + values, but short of passing #GVariants (which is ugly), we can't + do that in a introspectable way without a boxed struct +*/ +void +act_user_set_multiple_passwords (ActUser *user, + GHashTable *password_map) +{ + GError *error = NULL; + GcrSecretExchange *exchange; + GHashTableIter iter; + GVariantBuilder builder; + char *exchange_begin; + gpointer key, value; + + g_return_if_fail (ACT_IS_USER (user)); + g_return_if_fail (password_map != NULL); g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy)); - crypted = make_crypted (password); - if (!accounts_user_call_set_password_sync (user->accounts_proxy, - crypted, - hint, - NULL, - &error)) { - g_warning ("SetPassword call failed: %s", error->message); + if (!accounts_user_call_begin_set_password_sync (user->accounts_proxy, + &exchange_begin, + NULL, &error)) { + g_warning ("BeginSetPassword call failed: %s", error->message); + g_error_free (error); + return; + } + + exchange = gcr_secret_exchange_new (GCR_SECRET_EXCHANGE_PROTOCOL_1); + gcr_secret_exchange_receive (exchange, exchange_begin); + g_free (exchange_begin); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(us)")); + g_hash_table_iter_init (&iter, password_map); + while (g_hash_table_iter_next (&iter, &key, &value)) { + char *next_str; + + next_str = gcr_secret_exchange_send (exchange, value, -1); + g_variant_builder_add (&builder, "(us)", + GPOINTER_TO_INT (key), + next_str); + g_free (next_str); + } + + if (!accounts_user_call_continue_set_password_sync (user->accounts_proxy, + g_variant_builder_end (&builder), + NULL, + &error)) { + g_warning ("ContinueSetPassword call failed: %s", error->message); g_error_free (error); } - memset (crypted, 0, strlen (crypted)); - g_free (crypted); + + g_object_unref (exchange); } /** Index: accountsservice-0.6.35/src/pam-password-helper.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.35/src/pam-password-helper.c 2013-11-13 15:20:32.212131938 +0100 @@ -0,0 +1,169 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2012 Giovanni Campagna + * + * 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 + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +static char *password; +static char *old_password; +static char *pin; + +static int +answer_pam_message (int num_msg, + const struct pam_message **msg, + struct pam_response **resp, + void *appdata_ptr) +{ + int i; + struct pam_response *resps; + + /* Must use malloc here, not g_malloc (and same below, must + use strdup, not g_strdup) */ + resps = malloc((sizeof (struct pam_response)) * num_msg); + + /* We run non-interactively, so just copy the password + into each question, and hope that configuration is + correct. */ + /* Despite what's documented, msg is not a pointer + to an array of pointers. It's a pointer to a pointer + to an array of structures. Ugh! + */ + for (i = 0; i < num_msg; i++) { + if ((*msg)[i].msg_style == PAM_PROMPT_ECHO_OFF) { + const char *message = (*msg)[i].msg; + + if (old_password && strstr(message, "current") != NULL) + resps[i].resp = strdup(old_password); + else if (strcmp(message, "PIN") == 0) + resps[i].resp = pin ? strdup(pin) : NULL; + else + resps[i].resp = strdup(password); + } else { + resps[i].resp = NULL; + } + + resps[i].resp_retcode = 0; + + } + + *resp = resps; + + return PAM_SUCCESS; +} + +static char * +read_word (GIOChannel *from, + gboolean can_fail) +{ + char *str, *decoded; + gsize term_pos; + GIOStatus ok; + GError *error; + + error = NULL; + while ((ok = g_io_channel_read_line (from, + &str, + NULL, + &term_pos, + &error)) == G_IO_STATUS_AGAIN); + + if (ok == G_IO_STATUS_EOF && can_fail) + return NULL; + + if (ok != G_IO_STATUS_NORMAL) { + if (error) { + g_printerr ("Error reading from standard input: %s\n", error->message); + g_error_free (error); + } else { + g_printerr ("Generic error reading from standard input\n"); + } + + exit(PAM_AUTHTOK_ERR); + } + + str[term_pos] = 0; + + /* URI escaping is a simple form of encoding that avoids + ambiguity with \n while allowing arbitrary byte sequences */ + decoded = g_uri_unescape_string (str, ""); + + if (decoded == NULL) { + g_printerr ("Failed to decode password (probably contained a NUL).\n"); + exit(PAM_AUTHTOK_ERR); + } + + g_free (str); + return decoded; +} + +int +main (int argc, + char **argv) +{ + const char *username; + pam_handle_t *pamh; + struct pam_conv conv = { answer_pam_message, NULL }; + int res; + GIOChannel *stdin; + + if (argc != 2) { + g_printerr ("Wrong number of arguments passed, 1 expected\n"); + return PAM_AUTHTOK_ERR; + } + + username = argv[1]; + + stdin = g_io_channel_unix_new (STDIN_FILENO); + if (getuid() != 0) { + /* Running from the user session, read the old password first */ + old_password = read_word (stdin, FALSE); + } + + password = read_word (stdin, FALSE); + pin = read_word (stdin, TRUE); + g_io_channel_unref (stdin); + + res = pam_start ("accountsservice", username, + &conv, &pamh); + if (res != PAM_SUCCESS) { + /* pam_strerror can't be used without a pam handle */ + g_printerr ("Pam handle creation failed (not enough memory?)\n"); + return res; + } + + res = pam_chauthtok (pamh, PAM_SILENT); + if (res != PAM_SUCCESS) { + g_printerr ("Password change failed: %s\n", pam_strerror (pamh, res)); + } + pam_end (pamh, res); + + g_free (password); + g_free (pin); + + return res; +} Index: accountsservice-0.6.35/src/user.c =================================================================== --- accountsservice-0.6.35.orig/src/user.c 2013-11-13 15:20:32.228131938 +0100 +++ accountsservice-0.6.35/src/user.c 2013-11-13 15:20:32.216131938 +0100 @@ -42,6 +42,9 @@ #include #include +#define GCR_API_SUBJECT_TO_CHANGE +#include + #include "user-classify.h" #include "daemon.h" #include "user.h" @@ -86,6 +89,8 @@ GKeyFile *keyfile; + GHashTable *secret_exchanges; + uid_t uid; gid_t gid; gchar *user_name; @@ -2508,49 +2513,100 @@ return TRUE; } +static char * +build_pam_helper_stdin (const char *password, + const char *pin) +{ + char *encoded_pin, *encoded_password, *result; + + encoded_password = g_uri_escape_string (password, NULL, FALSE); + + if (pin != NULL) { + encoded_pin = g_uri_escape_string (pin, NULL, FALSE); + + result = g_strdup_printf ("%s\n%s\n", encoded_password, encoded_pin); + g_free (encoded_pin); + } else { + result = g_strdup_printf ("%s\n", encoded_password); + } + + g_free (encoded_password); + return result; +} + static void -user_change_password_authorized_cb (Daemon *daemon, - User *user, - GDBusMethodInvocation *context, - gpointer data) +user_continue_change_password_authorized_cb (Daemon *daemon, + User *user, + GDBusMethodInvocation *context, + gpointer data) { - gchar **strings = data; + GVariant *passwords = data; + GVariantIter iter; + GcrSecretExchange *exchange; GError *error; const gchar *argv[6]; + unsigned int type; + const char *encrypted_password; + char *password_hint, *password, *pin; + char *stdin; - sys_log (context, - "set password and hint of user '%s' (%d)", + sys_log (context, "change password of user '%s' (%d)", user->user_name, user->uid); + exchange = g_hash_table_lookup (user->secret_exchanges, + g_dbus_method_invocation_get_sender (context)); + g_object_ref (exchange); + g_hash_table_remove (user->secret_exchanges, g_dbus_method_invocation_get_sender (context)); + + if (exchange == NULL) { + /* The caller never called BeginSetPassword */ + throw_error (context, ERROR_INVALID, "secret exchange not initialized"); + return; + } + g_object_freeze_notify (G_OBJECT (user)); - argv[0] = "/usr/sbin/usermod"; - argv[1] = "-p"; - argv[2] = strings[0]; - argv[3] = "--"; - argv[4] = user->user_name; - argv[5] = NULL; + password_hint = NULL; + password = NULL; + pin = NULL; + g_variant_iter_init (&iter, passwords); + while (g_variant_iter_next (&iter, "(u&s)", &type, &encrypted_password)) { + if (!gcr_secret_exchange_receive (exchange, encrypted_password)) { + throw_error (context, ERROR_INVALID, "could not decrypt password"); + goto out; + } - error = NULL; - if (!spawn_with_login_uid (context, argv, &error)) { - throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); - g_error_free (error); - return; + switch (type) { + case 0: + g_free (password); + password = g_strdup (gcr_secret_exchange_get_secret (exchange, NULL)); + break; + case 1: + g_free (password_hint); + password_hint = g_strdup (gcr_secret_exchange_get_secret (exchange, NULL)); + break; + case 2: + g_free (pin); + pin = g_strdup (gcr_secret_exchange_get_secret (exchange, NULL)); + break; + + default: + throw_error (context, ERROR_INVALID, "invalid password type"); + goto out; + } } - /* Drop user from nopasswdlogin group */ - argv[0] = "/usr/bin/gpasswd"; - argv[1] = "-d"; - argv[2] = user->user_name; - argv[3] = "nopasswdlogin"; - argv[4] = NULL; + argv[0] = LIBEXECDIR "/accounts-daemon-pam-password-helper"; + argv[1] = user->user_name; + argv[2] = NULL; + stdin = build_pam_helper_stdin (password, pin); error = NULL; - if (!spawn_with_login_uid (context, argv, &error)) { + + if (!spawn_with_login_uid_and_stdin (context, argv, stdin, &error)) { throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); - g_error_free (error); - return; + goto out; } if (user->password_mode != PASSWORD_MODE_REGULAR) { @@ -2563,52 +2619,99 @@ g_object_notify (G_OBJECT (user), "locked"); } - if (g_strcmp0 (user->password_hint, strings[1]) != 0) { + if (password_hint != NULL && + g_strcmp0 (user->password_hint, password_hint) != 0) { g_free (user->password_hint); - user->password_hint = g_strdup (strings[1]); + /* An empty password hint means no password hint */ + if (*password_hint) + user->password_hint = g_strdup (password_hint); + else + user->password_hint = NULL; g_object_notify (G_OBJECT (user), "password-hint"); } save_extra_data (user); - g_object_thaw_notify (G_OBJECT (user)); - accounts_user_emit_changed (ACCOUNTS_USER (user)); - accounts_user_complete_set_password (ACCOUNTS_USER (user), context); -} + accounts_user_complete_continue_set_password (ACCOUNTS_USER (user), context); -static void -free_passwords (gchar **strings) -{ - memset (strings[0], 0, strlen (strings[0])); - g_strfreev (strings); + out: + g_free (password_hint); + g_free (password); + g_free (pin); + g_object_thaw_notify (G_OBJECT (user)); + g_object_unref (exchange); } static gboolean -user_set_password (AccountsUser *auser, - GDBusMethodInvocation *context, - const gchar *password, - const gchar *hint) +user_continue_set_password (AccountsUser *auser, + GDBusMethodInvocation *context, + GVariant *passwords) { User *user = (User*)auser; - gchar **data; - - data = g_new (gchar *, 3); - data[0] = g_strdup (password); - data[1] = g_strdup (hint); - data[2] = NULL; daemon_local_check_auth (user->daemon, user, "org.freedesktop.accounts.user-administration", TRUE, - user_change_password_authorized_cb, + user_continue_change_password_authorized_cb, context, - data, - (GDestroyNotify)free_passwords); + g_variant_ref (passwords), + (GDestroyNotify)g_variant_unref); + + return TRUE; +} - memset ((char*)password, 0, strlen (password)); +static void +on_name_vanished (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + User *user = USER (user_data); + + g_hash_table_remove (user->secret_exchanges, name); +} + +static void +on_exchange_unreffed (gpointer user_data, + GObject *object) +{ + g_bus_unwatch_name (GPOINTER_TO_INT (user_data)); +} + +static gboolean +user_begin_set_password (AccountsUser *auser, + GDBusMethodInvocation *context) +{ + User *user = (User*)auser; + const char *who; + GcrSecretExchange *exchange; + char *begin_str; + int name_id; + + who = g_dbus_method_invocation_get_sender (context); + exchange = g_hash_table_lookup (user->secret_exchanges, who); + + if (exchange != NULL) { + throw_error (context, ERROR_INVALID, "secret exchange already in progress"); + return TRUE; + } + + exchange = gcr_secret_exchange_new (GCR_SECRET_EXCHANGE_PROTOCOL_1); + g_hash_table_insert (user->secret_exchanges, g_strdup (who), exchange); + + name_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, who, + G_BUS_NAME_WATCHER_FLAGS_NONE, + NULL, /* name appeared */ + on_name_vanished, + auser, /* weak ref */ + NULL); + g_object_weak_ref (G_OBJECT (exchange), on_exchange_unreffed, GINT_TO_POINTER (name_id)); + + begin_str = gcr_secret_exchange_begin (exchange); + accounts_user_complete_begin_set_password (auser, context, begin_str); + g_free (begin_str); return TRUE; } @@ -2784,6 +2887,8 @@ g_clear_pointer (&user->keyfile, g_key_file_unref); + g_hash_table_unref (user->secret_exchanges); + g_free (user->object_path); g_free (user->user_name); g_free (user->real_name); @@ -2981,6 +3086,8 @@ iface->handle_set_language = user_set_language; iface->handle_set_location = user_set_location; iface->handle_set_locked = user_set_locked; + iface->handle_continue_set_password = user_continue_set_password; + iface->handle_begin_set_password = user_begin_set_password; iface->handle_set_password = user_set_password; iface->handle_set_password_mode = user_set_password_mode; iface->handle_set_real_name = user_set_real_name; @@ -3015,6 +3122,10 @@ { user->system_bus_connection = NULL; user->object_path = NULL; + + user->secret_exchanges = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_object_unref); + user->user_name = NULL; user->real_name = NULL; user->account_type = ACCOUNT_TYPE_STANDARD; Index: accountsservice-0.6.35/src/util.c =================================================================== --- accountsservice-0.6.35.orig/src/util.c 2013-11-13 15:20:32.228131938 +0100 +++ accountsservice-0.6.35/src/util.c 2013-11-13 15:20:32.216131938 +0100 @@ -259,6 +259,109 @@ return ret; } +static char * +read_all_from_fd (int fd, + GError **error) +{ + GIOChannel *channel; + char *str; + GIOStatus status; + + channel = g_io_channel_unix_new (fd); + while ((status = g_io_channel_read_to_end (channel, &str, NULL, error)) + == G_IO_STATUS_AGAIN); + + if (status != G_IO_STATUS_NORMAL) + str = NULL; + + g_io_channel_unref (channel); + return str; +} + +static GIOStatus +write_all_to_fd (int fd, + const char *str, + GError **error) +{ + GIOChannel *channel; + GIOStatus status; + gsize written; + + channel = g_io_channel_unix_new (fd); + written = 0; + while ((status = g_io_channel_write_chars (channel, str + written, -1, &written, error)) + == G_IO_STATUS_AGAIN); + + g_io_channel_unref (channel); + return status; +} + +gboolean +spawn_with_login_uid_and_stdin (GDBusMethodInvocation *context, + const gchar *argv[], + const gchar *stdin, + GError **error) +{ + GError *local_error; + gchar loginuid[20]; + gint std_in, std_err; + gint status; + char *std_err_str; + GPid pid; + + get_caller_loginuid (context, loginuid, 20); + + local_error = NULL; + + if (!g_spawn_async_with_pipes (NULL, (gchar**)argv, NULL, + G_SPAWN_DO_NOT_REAP_CHILD, + setup_loginuid, loginuid, + &pid, &std_in, NULL, &std_err, &local_error)) { + g_propagate_error (error, local_error); + return FALSE; + } + + if (write_all_to_fd (std_in, stdin, &local_error) == G_IO_STATUS_ERROR) { + g_prefix_error (&local_error, "Error writing to child standard input: "); + g_propagate_error (error, local_error); + close (std_in); + close (std_err); + return FALSE; + } + + close (std_in); + /* We need to read from stderr before calling waitpid, or the child + could be blocked on a pipe buffer flush */ + std_err_str = read_all_from_fd (std_err, &local_error); + /* At this point, it is safe to close std_err: EOF is returned from a pipe + read only when the writing end is closed, so when we return from read_all_from_fd() + the child is already done, and there is no risk of SIGPIPE + */ + close (std_err); + + waitpid (pid, &status, 0); + + if (std_err_str == NULL) { + g_prefix_error (&local_error, "Error reading from child standard error: "); + g_propagate_error (error, local_error); + return FALSE; + } + + if (WEXITSTATUS (status) != 0) { + g_set_error (error, + G_SPAWN_ERROR, + G_SPAWN_ERROR_FAILED, + "%s returned an error (%d): %s", + argv[0], WEXITSTATUS(status), std_err_str); + g_free (std_err_str); + return FALSE; + } + + g_free (std_err_str); + + return TRUE; +} + gint get_user_groups (const gchar *user, gid_t group, Index: accountsservice-0.6.35/src/util.h =================================================================== --- accountsservice-0.6.35.orig/src/util.h 2013-11-13 15:20:32.228131938 +0100 +++ accountsservice-0.6.35/src/util.h 2013-11-13 15:20:32.216131938 +0100 @@ -36,6 +36,11 @@ const gchar *argv[], GError **error); +gboolean spawn_with_login_uid_and_stdin (GDBusMethodInvocation *context, + const gchar *argv[], + const gchar *stdin, + GError **error); + gint get_user_groups (const gchar *username, gid_t group, gid_t **groups); Index: accountsservice-0.6.35/configure.ac =================================================================== --- accountsservice-0.6.35.orig/configure.ac 2013-11-13 15:20:32.228131938 +0100 +++ accountsservice-0.6.35/configure.ac 2013-11-13 15:20:32.220131938 +0100 @@ -27,13 +27,14 @@ PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.37.3 gio-unix-2.0) PKG_CHECK_MODULES(POLKIT, gio-unix-2.0 polkit-gobject-1) +PKG_CHECK_MODULES(GCR, gcr-base-3) AM_MAINTAINER_MODE([enable]) # client library dependencies -LIBACCOUNTSSERVICE_LIBS="$GIO_LIBS" +LIBACCOUNTSSERVICE_LIBS="$GIO_LIBS $GCR_LIBS" AC_SUBST(LIBACCOUNTSSERVICE_LIBS) -LIBACCOUNTSSERVICE_CFLAGS="$GIO_CFLAGS" +LIBACCOUNTSSERVICE_CFLAGS="$GIO_CFLAGS $GCR_CFLAGS" AC_SUBST(LIBACCOUNTSSERVICE_CFLAGS) GOBJECT_INTROSPECTION_CHECK([0.9.12]) @@ -281,6 +282,19 @@ fi AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != "xno" ]) +dnl --------------------------------------------------------------------------- +dnl PIN authentication support +dnl --------------------------------------------------------------------------- + +AC_ARG_ENABLE([pin-authentication], + AS_HELP_STRING([--disable-pin-authentication], [Disable PAM module for PIN (short password) login]), + [], + [enable_pin_authentication=yes]) +if test x$enable_pin_autentication != xno ; then + AM_PATH_LIBGCRYPT +fi +AM_CONDITIONAL(HAVE_PAM_MODULE, [test x$enable_pin_authentication != xno]) + AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([ Makefile @@ -290,6 +304,7 @@ src/Makefile src/libaccountsservice/Makefile src/libaccountsservice/accountsservice.pc +src/pam-pin/Makefile doc/Makefile doc/dbus/Makefile doc/dbus/AccountsService.xml Index: accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml =================================================================== --- accountsservice-0.6.35.orig/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:20:32.228131938 +0100 +++ accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:20:32.220131938 +0100 @@ -595,26 +595,54 @@ - + - + - The crypted password. + Unspecified opaque data that should be passed to gcr_secret_exchange_receive() - + + + + Begins a #GcrSecretExchange to set the new password for this user. + The expected next step is a call to ContinueSetPassword with the encrypted + passwords. + + + Note that setting a password has the side-effect of + unlocking the account. + + + + The caller does not need PolicyKit authorization, but the following ContinueSetPassword + might fail if the caller is not authorized. + + + + + + + + - The password hint. + The encrypted passwords. Each password is a DBus struct holding + - an unsigned integer specifying the kind of data: + - 0 if the password is a regular password + - 1 if the password is a really a hint (not a secret) + - 2 if the password is a PIN + - the result of calling gcr_secret_exchange_send(). The calls must + have been in the same order as they appear in the array. - Sets a new password for this user. + Sets a new password, hint and PIN for this user. Note that setting a password has the side-effect of @@ -633,6 +661,7 @@ if the caller lacks the appropriate PolicyKit authorization if the operation failed + if the caller did not call BeginSetPassword beforehand Index: accountsservice-0.6.35/src/daemon.c =================================================================== --- accountsservice-0.6.35.orig/src/daemon.c 2013-11-13 15:20:32.228131938 +0100 +++ accountsservice-0.6.35/src/daemon.c 2013-11-13 15:20:32.220131938 +0100 @@ -97,7 +97,8 @@ { 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" } + { ERROR_NOT_SUPPORTED, "org.freedesktop.Accounts.Error.NotSupported" }, + { ERROR_INVALID, "org.freedesktop.Accounts.Error.InvalidArguments" }, }; GQuark @@ -128,6 +129,7 @@ ENUM_ENTRY (ERROR_USER_DOES_NOT_EXIST, "UserDoesntExist"), ENUM_ENTRY (ERROR_PERMISSION_DENIED, "PermissionDenied"), ENUM_ENTRY (ERROR_NOT_SUPPORTED, "NotSupported"), + ENUM_ENTRY (ERROR_INVALID, "InvalidArguments"), { 0, 0, 0 } }; g_assert (NUM_ERRORS == G_N_ELEMENTS (values) - 1); Index: accountsservice-0.6.35/src/daemon.h =================================================================== --- accountsservice-0.6.35.orig/src/daemon.h 2013-11-13 15:20:32.228131938 +0100 +++ accountsservice-0.6.35/src/daemon.h 2013-11-13 15:20:32.220131938 +0100 @@ -57,6 +57,7 @@ ERROR_USER_DOES_NOT_EXIST, ERROR_PERMISSION_DENIED, ERROR_NOT_SUPPORTED, + ERROR_INVALID, NUM_ERRORS } Error; Index: accountsservice-0.6.35/src/libaccountsservice/act-user.h =================================================================== --- accountsservice-0.6.35.orig/src/libaccountsservice/act-user.h 2013-11-13 15:20:32.228131938 +0100 +++ accountsservice-0.6.35/src/libaccountsservice/act-user.h 2013-11-13 15:20:32.224131938 +0100 @@ -46,6 +46,12 @@ ACT_USER_PASSWORD_MODE_NONE, } ActUserPasswordMode; +typedef enum { + ACT_USER_PASSWORD_REGULAR, + ACT_USER_PASSWORD_HINT, + ACT_USER_PASSWORD_PIN +} ActUserPasswordType; + typedef struct _ActUser ActUser; typedef struct _ActUserClass ActUserClass; @@ -106,6 +112,8 @@ void act_user_set_password (ActUser *user, const gchar *password, const gchar *hint); +void act_user_set_multiple_passwords (ActUser *user, + GHashTable *password_map); void act_user_set_password_mode (ActUser *user, ActUserPasswordMode password_mode); void act_user_set_locked (ActUser *user, Index: accountsservice-0.6.35/src/pam-pin/Makefile.am =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.35/src/pam-pin/Makefile.am 2013-11-13 15:20:32.224131938 +0100 @@ -0,0 +1,16 @@ +securitydir = $(libdir)/security + +security_LTLIBRARIES = pam_pin.la + +pam_pin_la_SOURCES = pam-module.c +pam_pin_la_LDFLAGS = -module -avoid-version +pam_pin_la_LIBADD = $(LIBGCRYPT_LIBS) $(GIO_LIBS) +pam_pin_la_CFLAGS = \ + -DLOCALSTATEDIR=\""$(localstatedir)"\" \ + -DDATADIR=\""$(datadir)"\" \ + -DUSERDIR=\"$(localstatedir)/lib/AccountsService/users\" \ + -DPASSWDDIR=\"$(localstatedir)/lib/AccountsService/encrypted-password\" \ + -DLIBEXECDIR=\"$(libexecdir)\" \ + $(LIBGCRYPT_CFLAGS) \ + $(GIO_CFLAGS) \ + $(WARN_CFLAGS) Index: accountsservice-0.6.35/src/pam-pin/pam-module.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.35/src/pam-pin/pam-module.c 2013-11-13 15:20:32.224131938 +0100 @@ -0,0 +1,422 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2012 Giovanni Campagna + * + * 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 + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* We use AES256 in Cipher Block Chaining mode, + using a key derived from the PIN, salted with the machine id + and passed through PBKDF2. +*/ +#define KEY_LENGTH 256/8 +#define N_ITERATIONS 100000 + +static void +init_libgcrypt (void) +{ + /* Despite the name, this is a library init function... */ + gcry_check_version (GCRYPT_VERSION); +} + +static char * +make_key (const char *pin) +{ + char *key; + char *machine_id; + size_t machine_id_len; + + if (!g_file_get_contents ("/etc/machine-id", &machine_id, + &machine_id_len, NULL)) + return NULL; + + key = g_malloc (KEY_LENGTH); + + if (gcry_kdf_derive (pin, strlen (pin), + GCRY_KDF_PBKDF2, GCRY_MD_SHA1, + machine_id, machine_id_len, + N_ITERATIONS, KEY_LENGTH, key)) { + g_free (key); + key = NULL; + } + + g_free (machine_id); + return key; +} + +static size_t +get_block_size (void) +{ + size_t sz; + + gcry_cipher_algo_info (GCRY_CIPHER_AES256, GCRYCTL_GET_BLKLEN, NULL, &sz); + return sz; +} + +static char * +make_iv (void) +{ + char *iv; + size_t sz; + + sz = get_block_size (); + iv = g_malloc (sz); + memset(iv, 0, sz); + + return iv; +} + +static char * +make_padded_password (const char *password, + size_t *out_size) +{ + size_t total; + size_t blksz; + size_t current; + char *padded; + + blksz = get_block_size (); + current = strlen (password); + + if (current % blksz) { + total = (current / blksz + 1) * blksz; + padded = g_malloc (total + 1); + stpncpy (padded, password, total + 1); + + *out_size = total; + return padded; + } else { + *out_size = current; + return g_strdup (password); + } +} + +static char * +decode_password (const char *ciphertext, + size_t ciphertext_len, + const char *pin) +{ + gcry_cipher_hd_t hd = NULL; + char *key = NULL; + char *iv = NULL; + char *password = NULL; + + key = make_key (pin); + if (key == NULL) + return NULL; + + if (gcry_cipher_open (&hd, GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_CBC, 0)) + goto out; + + iv = make_iv (); + gcry_cipher_setiv (hd, iv, get_block_size ()); + gcry_cipher_setkey (hd, key, KEY_LENGTH); + + password = g_malloc (ciphertext_len + 1); + if (password == NULL) + goto out; + + if (gcry_cipher_decrypt (hd, password, ciphertext_len, + ciphertext, ciphertext_len)) { + g_free (password); + password = NULL; + } else { + password[ciphertext_len] = 0; + } + + out: + g_free (key); + g_free (iv); + gcry_cipher_close (hd); + return password; +} + +static char * +encode_password (const char *password, + const char *pin, + size_t *ciphertext_len) +{ + gcry_cipher_hd_t hd = NULL; + char *key = NULL; + char *iv = NULL; + char *ciphertext = NULL; + char *padded = NULL; + size_t password_len; + + key = make_key (pin); + if (key == NULL) + return NULL; + + if (gcry_cipher_open (&hd, GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_CBC, 0)) + goto out; + + iv = make_iv (); + gcry_cipher_setiv (hd, iv, get_block_size ()); + gcry_cipher_setkey (hd, key, KEY_LENGTH); + + padded = make_padded_password (password, &password_len); + *ciphertext_len = password_len; + ciphertext = g_malloc(*ciphertext_len + 1); + + if (gcry_cipher_encrypt (hd, ciphertext, password_len, + padded, password_len)) { + g_free (ciphertext); + ciphertext = NULL; + } + + out: + g_free (key); + g_free (iv); + g_free (padded); + gcry_cipher_close (hd); + return ciphertext; +} + +int +pam_sm_authenticate (pam_handle_t *handle, + int flags, + int argc, + const char **argv) +{ + const char *username; + char *filename = NULL; + char *ciphertext = NULL; + size_t ciphertext_len; + const char *pin; + char *password; + int result; + GError *error; + + init_libgcrypt (); + + /* We require CAP_DAC_OVERRIDE to access the encrypted password + (like /etc/shadow) */ + if (g_mkdir_with_parents (PASSWDDIR, 0) < 0) + return PAM_AUTHINFO_UNAVAIL; + + /* Username must not be localized, there is an exact match + in gnome-shell */ + result = pam_get_user (handle, &username, "Username: "); + if (result != PAM_SUCCESS) + return result; + + filename = g_build_filename (PASSWDDIR, username, NULL); + + error = NULL; + if (!g_file_get_contents (filename, &ciphertext, &ciphertext_len, &error)) { + if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) + result = PAM_AUTHINFO_UNAVAIL; + else + result = PAM_AUTHTOK_ERR; + + g_error_free (error); + goto out; + } + + /* Do not translate this string, it's a marker used by gnome-shell + to show the PIN keypad */ + result = pam_get_authtok (handle, PAM_AUTHTOK, &pin, "PIN"); + if (result != PAM_SUCCESS) + goto out; + + password = decode_password (ciphertext, ciphertext_len, pin); + if (password) + result = pam_set_item (handle, PAM_AUTHTOK, password); + else + result = PAM_AUTH_ERR; + + out: + g_free (ciphertext); + g_free (filename); + + return result; +} + +static int +do_preliminary_check(pam_handle_t *handle) +{ + char *filename; + const char *username; + int result, fd; + + if (g_mkdir_with_parents (PASSWDDIR, 0) < 0) + return PAM_AUTHINFO_UNAVAIL; + + result = pam_get_user (handle, &username, "Username: "); + if (result != PAM_SUCCESS) + return result; + + /* Check that we can access and write the database */ + filename = g_build_filename (PASSWDDIR, username, NULL); + + fd = open(filename, O_RDWR); + if (fd < 0 && errno != ENOENT) + result = PAM_AUTHTOK_ERR; + else + result = PAM_SUCCESS; + + g_free(filename); + if (fd >= 0) + close(fd); + return result; +} + +static int +request_and_encrypt_pin(pam_handle_t *handle, + const char *username, + char **ciphertext, + size_t *ciphertext_len) +{ + const char *password; + char *pin; + int result; + + *ciphertext = NULL; + + result = pam_get_authtok (handle, PAM_AUTHTOK, &password, "Password: "); + if (result != PAM_SUCCESS) + return result; + + result = pam_prompt (handle, PAM_PROMPT_ECHO_OFF, &pin, "PIN"); + if (result != PAM_SUCCESS) + return result; + + if (pin == NULL || strlen (pin) == 0) { + result = PAM_SUCCESS; + } else { + *ciphertext = encode_password (password, pin, ciphertext_len); + if (!*ciphertext) + result = PAM_AUTHTOK_ERR; + else + result = PAM_SUCCESS; + } + + /* Don't use g_free here, the string comes from PAM */ + free(pin); + return result; +} + +static int +do_change_authtok(pam_handle_t *handle) +{ + const char *username; + char *filename; + char *ciphertext; + size_t ciphertext_len; + int result, ok; + uid_t ruid, euid; + + result = pam_get_user (handle, &username, "Username: "); + if (result != PAM_SUCCESS) + return result; + + filename = g_build_filename (PASSWDDIR, username, NULL); + + ciphertext = NULL; + result = PAM_AUTHTOK_ERR; + + /* libgcrypt has the interesting habit to drop + all privileges when allocating secure memory, + and it does so with setuid() instead of seteuid() + Workaround that by dropping the priviliges ourselves + and then regaining them before leaving control to + the rest of the PAM stack. + + This is not thread-safe and very, very bad in general! + */ + ruid = getuid(); + euid = geteuid(); + + if (euid != ruid) { + ok = seteuid(ruid); + if (ok < 0) + goto out; + } + + result = request_and_encrypt_pin (handle, username, + &ciphertext, &ciphertext_len); + + ok = seteuid (euid); + + if (result != PAM_SUCCESS) + goto out; + if (ok < 0) { + result = PAM_AUTHTOK_ERR; + goto out; + } + + if (ciphertext) { + if (!g_file_set_contents (filename, ciphertext, ciphertext_len, NULL)) + goto out; + + /* Set file mode to 0, and require DAC_OVERRIDE to access it */ + if (chmod (filename, 0) < 0) + goto out; + } else { + if (unlink (filename) < 0 && errno != ENOENT) + goto out; + } + + result = PAM_SUCCESS; + + out: + g_free(filename); + g_free(ciphertext); + return result; +} + +int +pam_sm_setcred(pam_handle_t *handle, + int flags, + int argc, + const char **argv) +{ + return PAM_SUCCESS; +} + +int +pam_sm_chauthtok (pam_handle_t *handle, + int flags, + int argc, + const char **argv) +{ + init_libgcrypt (); + + if (flags & PAM_PRELIM_CHECK) + return do_preliminary_check(handle); + else if (flags & PAM_UPDATE_AUTHTOK) + return do_change_authtok(handle); + + return PAM_SUCCESS; +} debian/patches/0010-set-language.patch0000664000000000000000000004164212240704726014605 0ustar Description: Save user language and regional formats settings to ~/.pam_environment. Author: Gunnar Hjalmarsson Index: accountsservice-0.6.35/src/user.c =================================================================== --- accountsservice-0.6.35.orig/src/user.c 2013-11-13 15:16:53.000125338 +0100 +++ accountsservice-0.6.35/src/user.c 2013-11-13 15:16:52.996125337 +0100 @@ -1071,6 +1071,297 @@ return TRUE; } +static gboolean +user_drop_privileges_to_user (User *user) +{ + if (setresgid (user->gid, user->gid, -1) != 0) { + g_warning ("setresgid() failed"); + return FALSE; + } + if (setresuid (user->uid, user->uid, -1) != 0) { + g_warning ("setresuid() failed"); + return FALSE; + } + return TRUE; +} + +static void +user_regain_privileges () +{ + if (setresuid (0, 0, -1) != 0) + g_warning ("setresuid() failed"); + if (setresgid (0, 0, -1) != 0) + g_warning ("setresgid() failed"); +} + +static gchar * +user_locale_utf8_fix (const gchar *locale) +{ + if (locale == NULL || !g_strrstr (locale, ".utf8")) + return g_strdup (locale); + + gchar **tokens = g_strsplit_set (locale, ".8", 3); + gchar *fixed_locale = g_strconcat (tokens[0], ".UTF-8", tokens[2], NULL); + g_strfreev (tokens); + + return fixed_locale; +} + +static gchar * +user_language_validate (User *user, + const gchar *lang) +{ + gboolean ret; + const gchar *program = "/usr/share/language-tools/language-validate"; + gchar *command = g_strconcat (program, " ", lang, NULL); + gchar *validated_language; + GError *error = NULL; + + if (!user_drop_privileges_to_user (user)) + return NULL; + ret = g_spawn_command_line_sync (command, &validated_language, NULL, NULL, &error); + user_regain_privileges (); + + g_free (command); + if (!ret) { + g_warning ("Couldn't get validated language: %s", error->message); + g_error_free (error); + return NULL; + } + return g_strchomp (validated_language); +} + +static gchar * +user_locale_validate (User *user, + const gchar *locale, + GDBusMethodInvocation *context) +{ + gchar *validated_locale = NULL; + gchar *tmp_locale = NULL; + gchar *tmp_locale_utf8 = NULL; + gboolean ret = FALSE; + gchar *output = NULL; + GError *error = NULL; + gboolean found = FALSE; + + if (locale == NULL || strlen (locale) < 2) + goto out; + tmp_locale = g_strdup (locale); + g_strchomp (tmp_locale); + + /* When a new language has been installed, we want to be able to instantly + set a locale for that language to denote the regional formats. For that + reason we make use of 'locale -a' instead of calling setlocale(). */ + + if (!user_drop_privileges_to_user (user)) + goto out; + ret = g_spawn_command_line_sync ("locale -a", &output, NULL, NULL, &error); + user_regain_privileges (); + if (!ret) { + throw_error (context, ERROR_FAILED, "Failed to run 'locale -a': %s", error->message); + g_clear_error (&error); + goto out; + } + + /* Replace 'UTF-8' with 'utf8' since 'locale -a' outputs the latter. */ + tmp_locale_utf8 = g_strdup (tmp_locale); + if (g_strrstr (tmp_locale_utf8, ".UTF-8")) { + gchar **tokens = g_strsplit_set (tmp_locale_utf8, ".8", 3); + g_free (tmp_locale_utf8); + tmp_locale_utf8 = g_strconcat (tokens[0], ".utf8", tokens[2], NULL); + g_strfreev (tokens); + } + + gchar **tokens; + int i; + g_strchomp (output); + tokens = g_strsplit (output, "\n", -1); + for (i = 0; tokens[i]; i++) { + if (g_strcmp0 (tokens[i], "C") == 0 || + g_strcmp0 (tokens[i], "C.UTF-8") == 0 || + g_strcmp0 (tokens[i], "POSIX") == 0) + continue; + + if (g_strcmp0 (tokens[i], tmp_locale_utf8) == 0) { + found = TRUE; + break; + } + } + g_strfreev (tokens); + + if (!found) { + throw_error (context, ERROR_FAILED, "'%s' is not a valid locale name", tmp_locale); + goto out; + } + validated_locale = user_locale_utf8_fix (tmp_locale); + +out: + g_free (tmp_locale); + g_free (tmp_locale_utf8); + g_free (output); + + return validated_locale; +} + +static gchar * +strip_quotes (const gchar *str) +{ + if ((g_str_has_prefix (str, "\"") && g_str_has_suffix (str, "\"")) + || (g_str_has_prefix (str, "'") && g_str_has_suffix (str, "'"))) + return g_strndup (str + 1, strlen (str) - 2); + else + return g_strdup (str); +} + +static gchar * +user_get_fallback_value (User *user, + const gchar *property) +{ + gchar *fallback_value = NULL; + gchar *language = NULL; + gchar *lang = NULL; + gchar *lctime = NULL; + + FILE *fp; + if ((fp = fopen ("/etc/default/locale", "r"))) { + gchar line[50]; + while ((fgets (line, 50, fp)) != NULL) { + g_strchomp (line); + if (g_str_has_prefix (line, "LANGUAGE=")) + language = strip_quotes (line + strlen ("LANGUAGE=")); + else if (g_str_has_prefix (line, "LANG=")) + lang = strip_quotes (line + strlen ("LANG=")); + else if (g_str_has_prefix (line, "LC_TIME=")) + lctime = strip_quotes (line + strlen ("LC_TIME=")); + } + fclose (fp); + } + + if (g_strcmp0 (property, "Language") == 0) { + gchar *tmp = NULL; + if (language) + tmp = language; + else if (lang) + tmp = lang; + fallback_value = user_language_validate (user, tmp); + } + + if (g_strcmp0 (property, "FormatsLocale") == 0) { + gchar *tmp = NULL; + if (lctime) + tmp = lctime; + else if (lang) + tmp = lang; + fallback_value = user_locale_utf8_fix (tmp); + } + + g_free (language); + g_free (lang); + g_free (lctime); + + return fallback_value; +} + +static gchar * +user_update_environment (User *user, + gchar *data, + const gchar *script, + GDBusMethodInvocation *context) + +/* This function updates ~/.pam_environment by means of the help files in /usr/share/language-tools. */ +{ + gchar *program; + gchar *validated_data = NULL; + gint i; + const gchar *allowed_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._+-:/ @"; + gboolean ret; + GError *error = NULL; + + if (data == NULL) + return NULL; + + program = g_build_path ("/", "/usr/share/language-tools", script, NULL); + gchar *command[] = { program, user->home_dir, data, NULL }; + + /* test for odd characters in arguments */ + for (i = 1; i <= 2; i++) { + if (strlen (command[i]) != strspn (command[i], allowed_chars)) { + throw_error (context, ERROR_FAILED, "non-permitted character(s) in argument"); + goto out; + } + } + + /* set applicable environment variables in ~/.pam_environment */ + if (!user_drop_privileges_to_user (user)) + goto out; + ret = g_spawn_sync ( NULL, + command, + NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, + NULL, + &validated_data, + NULL, + NULL, + &error ); + user_regain_privileges (); + if (!ret) { + throw_error (context, ERROR_FAILED, "running '%s' failed: %s", program, error->message); + g_error_free (error); + validated_data = NULL; + goto out; + } + if (validated_data == NULL || strlen (validated_data) <= 1) { + throw_error (context, ERROR_FAILED, "running '%s' failed: no output", program); + validated_data = NULL; + goto out; + } + +out: + g_free (program); + if (validated_data == NULL) + return NULL; + + return g_strchomp (validated_data); +} + +static gboolean +user_HOME_available (User *user) +{ + /* run these tests as user to prevent incorrect + failures when HOME is on NFS */ + user_drop_privileges_to_user (user); + + GDir* homedir = g_dir_open (user->home_dir, 0, NULL); + + if (homedir == NULL) { // HOME not found + user_regain_privileges (); + return FALSE; + } else { + do { + const gchar *entry = g_dir_read_name (homedir); + gchar *path_to_entry = g_build_path ("/", user->home_dir, entry, NULL); + if (g_file_test (path_to_entry, G_FILE_TEST_IS_SYMLINK)) { + g_free (path_to_entry); + continue; + } + if (g_strcmp0 (entry, NULL) == 0) { // HOME contains only symlinks + g_free (path_to_entry); + g_dir_close (homedir); + user_regain_privileges (); + return FALSE; + } else + g_free (path_to_entry); + break; + } while (TRUE); + } + + g_dir_close (homedir); + user_regain_privileges (); + + return TRUE; +} + static void user_change_language_authorized_cb (Daemon *daemon, User *user, @@ -1078,11 +1369,78 @@ gpointer data) { - gchar *language = data; + const gchar *fallback_language = user_get_fallback_value (user, "Language"); + gboolean is_language_changed = (user->language && g_strcmp0 (user->language, data) != 0) + || (!user->language && g_strcmp0 (data, fallback_language) != 0); + + if (!user_HOME_available (user)) { + + /* SetLanguage was probably called from a login greeter, + and HOME not mounted and/or not decrypted. + Hence don't save anything, or else accountsservice + and ~/.pam_environment would become out of sync. */ + throw_error (context, ERROR_FAILED, "not access to HOME yet so language not saved"); + goto out2; + } + + if (is_language_changed) { + gchar *language = user_update_environment (user, + data, + "set-language-helper", + context); + if (language != NULL) { + g_free (user->language); + user->language = language; + } + + gchar *locale = NULL; - if (g_strcmp0 (user->language, language) != 0) { - g_free (user->language); - user->language = g_strdup (language); + if (!user->formats_locale) { + + /* set the user formats (certain LC_* variables) explicitly + in order to prevent surprises when LANG is changed */ + FILE *fp; + if ((fp = fopen ("/etc/default/locale", "r"))) { + gchar line[50]; + while ((fgets (line, 50, fp)) != NULL) { + if (g_str_has_prefix (line, "LC_TIME=")) { + g_strchomp (line); + locale = strip_quotes (line + strlen ("LC_TIME=")); + break; + } + } + fclose (fp); + } + if (locale == NULL) { + GError *error = NULL; + const gchar *program = "/usr/share/language-tools/language2locale"; + if (!user_drop_privileges_to_user (user)) + goto out1; + gchar *command = g_strconcat (program, " ", fallback_language, NULL); + gboolean ret = g_spawn_command_line_sync (command, &locale, NULL, NULL, &error); + user_regain_privileges (); + if (!ret) { + throw_error (context, ERROR_FAILED, + "language-to-locale conversion failed: %s", error->message); + g_error_free (error); + locale = NULL; + } + g_free (command); + } + } + + if (locale != NULL && strlen (locale) > 0) { + gchar *formats_locale = user_update_environment (user, + user_locale_validate (user, locale, context), + "save-to-pam-env", + context); + if (formats_locale != NULL) { + g_free (user->formats_locale); + user->formats_locale = formats_locale; + } + } +out1: + g_free (locale); save_extra_data (user); @@ -1091,6 +1449,7 @@ g_object_notify (G_OBJECT (user), "language"); } +out2: accounts_user_complete_set_language (ACCOUNTS_USER (user), context); } @@ -1134,11 +1493,15 @@ gpointer data) { - gchar *formats_locale = data; - - if (g_strcmp0 (user->formats_locale, formats_locale) != 0) { - g_free (user->formats_locale); - user->formats_locale = g_strdup (formats_locale); + if (g_strcmp0 (user->formats_locale, data) != 0) { + gchar *formats_locale = user_update_environment (user, + user_locale_validate (user, data, context), + "save-to-pam-env", + context); + if (formats_locale != NULL) { + g_free (user->formats_locale); + user->formats_locale = formats_locale; + } save_extra_data (user); @@ -2325,10 +2688,16 @@ g_value_set_string (value, user->email); break; case PROP_LANGUAGE: - g_value_set_string (value, user->language); + if (user->language) + g_value_set_string (value, user->language); + else + g_value_set_string (value, user_get_fallback_value (user, "Language")); break; case PROP_FORMATS_LOCALE: - g_value_set_string (value, user->formats_locale); + if (user->formats_locale) + g_value_set_string (value, user->formats_locale); + else + g_value_set_string (value, user_get_fallback_value (user, "FormatsLocale")); break; case PROP_X_SESSION: g_value_set_string (value, user->x_session); debian/patches/0016-add-input-sources-support.patch0000664000000000000000000005074312240705442017315 0ustar From eebb604999d40ee4d3151536e6e4086735556378 Mon Sep 17 00:00:00 2001 From: William Hua Date: Fri, 26 Jul 2013 10:10:11 -0400 Subject: [PATCH] Store input sources in user objects. --- data/org.freedesktop.Accounts.User.xml | 45 +++++++ src/libaccountsservice/act-user.c | 82 +++++++++++++ src/libaccountsservice/act-user.h | 3 + src/user.c | 212 +++++++++++++++++++++++++++++++++ 4 files changed, 342 insertions(+) Index: accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml =================================================================== --- accountsservice-0.6.35.orig/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:22:20.912135211 +0100 +++ accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:22:20.900135210 +0100 @@ -185,6 +185,41 @@ + + + + + + A list of input sources. + + + + + + + Sets the user's input sources. + + + + The caller needs one of the following PolicyKit authorizations: + + + org.freedesktop.accounts.change-own-user-data + To change his own input sources + + + org.freedesktop.accounts.user-administration + To change the input sources of another user + + + + + if the caller lacks the appropriate PolicyKit authorization + if the operation failed + + + + @@ -843,6 +878,16 @@ + + + + + + + The user's input sources. + + + Index: accountsservice-0.6.35/src/libaccountsservice/act-user.c =================================================================== --- accountsservice-0.6.35.orig/src/libaccountsservice/act-user.c 2013-11-13 15:22:20.912135211 +0100 +++ accountsservice-0.6.35/src/libaccountsservice/act-user.c 2013-11-13 15:22:20.900135210 +0100 @@ -100,6 +100,7 @@ PROP_ICON_FILE, PROP_LANGUAGE, PROP_FORMATS_LOCALE, + PROP_INPUT_SOURCES, PROP_X_SESSION, PROP_IS_LOADED }; @@ -132,6 +133,7 @@ char *icon_file; char *language; char *formats_locale; + GVariant *input_sources; char *x_session; GList *our_sessions; GList *other_sessions; @@ -331,6 +333,9 @@ case PROP_FORMATS_LOCALE: g_value_set_string (value, user->formats_locale); break; + case PROP_INPUT_SOURCES: + g_value_set_variant (value, user->input_sources); + break; case PROP_X_SESSION: g_value_set_string (value, user->x_session); break; @@ -515,6 +520,14 @@ NULL, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, + PROP_INPUT_SOURCES, + g_param_spec_variant ("input-sources", + "Input sources", + "User's input sources.", + G_VARIANT_TYPE ("aa{ss}"), + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, PROP_X_SESSION, g_param_spec_string ("x-session", "X session", @@ -634,6 +647,8 @@ g_free (user->shell); g_free (user->email); g_free (user->location); + if (user->input_sources) + g_variant_unref (user->input_sources); if (user->login_history) g_variant_unref (user->login_history); g_free (user->formats_locale); @@ -1170,6 +1185,22 @@ } /** + * act_user_get_input_sources: + * @user: a #ActUser + * + * Returns the input sources of @user. + * + * Returns: (transfer none): a list of input sources + */ +GVariant * +act_user_get_input_sources (ActUser *user) +{ + g_return_val_if_fail (ACT_IS_USER (user), NULL); + + return user->input_sources; +} + +/** * act_user_get_x_session: * @user: a #ActUser * @@ -1456,6 +1487,19 @@ g_object_notify (G_OBJECT (user), "formats_locale"); } + } else if (strcmp (key, "InputSources") == 0) { + GVariant *sources; + + g_variant_get (value, "@aa{ss}", &sources); + + if (!user->input_sources || !g_variant_equal (sources, user->input_sources)) { + if (user->input_sources) + g_variant_unref (user->input_sources); + user->input_sources = g_variant_ref (sources); + g_object_notify (G_OBJECT (user), "input-sources"); + } + + g_variant_unref (sources); } else if (strcmp (key, "XSession") == 0) { const char *new_x_session; @@ -1712,6 +1756,15 @@ user->language = g_strdup (user_to_copy->language); g_object_notify (G_OBJECT (user), "language"); + if (user_to_copy->input_sources != user->input_sources) { + if (user->input_sources) + g_variant_unref (user->input_sources); + user->input_sources = user_to_copy->input_sources; + if (user->input_sources) + g_variant_ref (user->input_sources); + g_object_notify (G_OBJECT (user), "input-sources"); + } + g_free (user->x_session); user->x_session = g_strdup (user_to_copy->x_session); g_object_notify (G_OBJECT (user), "x-session"); @@ -1895,6 +1948,35 @@ g_error_free (error); return; } +} + +/** + * act_user_set_input_sources: + * @user: the user object to alter. + * @sources: a list of input sources + * + * Assigns new input sources for @user. + * + * Note this function is synchronous and ignores errors. + **/ +void +act_user_set_input_sources (ActUser *user, + GVariant *sources) +{ + GError *error = NULL; + + g_return_if_fail (ACT_IS_USER (user)); + g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy)); + g_return_if_fail (g_variant_is_of_type (sources, G_VARIANT_TYPE ("aa{ss}"))); + + if (!accounts_user_call_set_input_sources_sync (user->accounts_proxy, + sources, + NULL, + &error)) { + g_warning ("SetInputSources call failed: %s", error->message); + g_error_free (error); + return; + } } /** Index: accountsservice-0.6.35/src/libaccountsservice/act-user.h =================================================================== --- accountsservice-0.6.35.orig/src/libaccountsservice/act-user.h 2013-11-13 15:22:20.912135211 +0100 +++ accountsservice-0.6.35/src/libaccountsservice/act-user.h 2013-11-13 15:22:20.900135210 +0100 @@ -84,6 +84,7 @@ const char *act_user_get_icon_file (ActUser *user); const char *act_user_get_language (ActUser *user); const char *act_user_get_formats_locale (ActUser *user); +GVariant *act_user_get_input_sources (ActUser *user); const char *act_user_get_x_session (ActUser *user); const char *act_user_get_primary_session_id (ActUser *user); @@ -97,6 +98,8 @@ const char *language); void act_user_set_formats_locale (ActUser *user, const char *formats_locale); +void act_user_set_input_sources (ActUser *user, + GVariant *sources); void act_user_set_x_session (ActUser *user, const char *x_session); void act_user_set_location (ActUser *user, Index: accountsservice-0.6.35/src/user.c =================================================================== --- accountsservice-0.6.35.orig/src/user.c 2013-11-13 15:22:20.912135211 +0100 +++ accountsservice-0.6.35/src/user.c 2013-11-13 15:22:20.904135211 +0100 @@ -63,6 +63,7 @@ PROP_EMAIL, PROP_LANGUAGE, PROP_FORMATS_LOCALE, + PROP_INPUT_SOURCES, PROP_X_SESSION, PROP_LOCATION, PROP_LOGIN_FREQUENCY, @@ -104,6 +105,7 @@ gchar *email; gchar *language; gchar *formats_locale; + GVariant *input_sources; gchar *x_session; gchar *location; guint64 login_frequency; @@ -330,6 +332,75 @@ accounts_user_emit_changed (ACCOUNTS_USER (user)); } +static gint +intcmp (gconstpointer a, + gconstpointer b, + gpointer user_data) +{ + return GPOINTER_TO_INT (a) - GPOINTER_TO_INT (b); +} + +static GVariant * +key_file_get_input_sources (GKeyFile *key_file) +{ + GVariantBuilder builder; + GSequence *indices; + GSequenceIter *indices_iter; + gchar **groups; + gchar **groups_iter; + + indices = g_sequence_new (NULL); + groups = g_key_file_get_groups (key_file, NULL); + + for (groups_iter = groups; *groups_iter; groups_iter++) { + if (g_str_has_prefix (*groups_iter, "InputSource") && (*groups_iter)[11]) { + gchar *end; + guint64 index; + + index = g_ascii_strtoull (*groups_iter + 11, &end, 0); + + if (!*end) + g_sequence_insert_sorted (indices, GINT_TO_POINTER (index), intcmp, NULL); + } + } + + g_strfreev (groups); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{ss}")); + + indices_iter = g_sequence_get_begin_iter (indices); + + while (!g_sequence_iter_is_end (indices_iter)) { + guint index; + gchar *group; + gchar **keys; + gchar **keys_iter; + + g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{ss}")); + + index = GPOINTER_TO_UINT (g_sequence_get (indices_iter)); + group = g_strdup_printf ("InputSource%u", index); + keys = g_key_file_get_keys (key_file, group, NULL, NULL); + + for (keys_iter = keys; *keys_iter; keys_iter++) { + gchar *value = g_key_file_get_string (key_file, group, *keys_iter, NULL); + g_variant_builder_add (&builder, "{ss}", *keys_iter, value); + g_free (value); + } + + g_strfreev (keys); + g_free (group); + + g_variant_builder_close (&builder); + + indices_iter = g_sequence_iter_next (indices_iter); + } + + g_sequence_free (indices); + + return g_variant_ref_sink (g_variant_builder_end (&builder)); +} + void user_update_from_keyfile (User *user, GKeyFile *keyfile) @@ -353,6 +424,11 @@ g_object_notify (G_OBJECT (user), "formats-locale"); } + if (user->input_sources != NULL) + g_variant_unref (user->input_sources); + user->input_sources = key_file_get_input_sources (keyfile); + g_object_notify (G_OBJECT (user), "input-sources"); + s = g_key_file_get_string (keyfile, "User", "XSession", NULL); if (s != NULL) { g_free (user->x_session); @@ -439,6 +515,51 @@ } static void +key_file_set_input_sources (GKeyFile *key_file, + GVariant *input_sources) +{ + gchar **groups; + gchar **groups_iter; + GVariantIter sources; + GVariantIter *source; + guint i; + + /* Remove all groups matching regex "InputSource\d+". */ + + groups = g_key_file_get_groups (key_file, NULL); + + for (groups_iter = groups; *groups_iter; groups_iter++) { + if (g_str_has_prefix (*groups_iter, "InputSource")) { + for (i = 11; g_ascii_isdigit ((*groups_iter)[i]); i++); + + if (i > 11 && !(*groups_iter)[i]) + g_key_file_remove_group (key_file, *groups_iter, NULL); + } + } + + g_strfreev (groups); + + /* Write all input sources to key file. */ + + g_variant_iter_init (&sources, input_sources); + + for (i = 0; g_variant_iter_next (&sources, "a{ss}", &source); i++) { + gchar *group; + const gchar *key; + const gchar *value; + + group = g_strdup_printf ("InputSource%u", i); + + while (g_variant_iter_next (source, "{&s&s}", &key, &value)) + g_key_file_set_string (key_file, group, key, value); + + g_free (group); + + g_variant_iter_free (source); + } +} + +static void user_save_to_keyfile (User *user, GKeyFile *keyfile) { @@ -453,6 +574,9 @@ if (user->formats_locale) g_key_file_set_string (keyfile, "User", "FormatsLocale", user->formats_locale); + if (user->input_sources) + key_file_set_input_sources (keyfile, user->input_sources); + if (user->x_session) g_key_file_set_string (keyfile, "User", "XSession", user->x_session); @@ -1578,6 +1702,67 @@ } static void +user_change_input_sources_authorized_cb (Daemon *daemon, + User *user, + GDBusMethodInvocation *context, + gpointer data) + +{ + GVariant *sources = data; + + if (sources != user->input_sources && + (!sources || !user->input_sources || + !g_variant_equal (sources, user->input_sources))) { + if (user->input_sources) + g_variant_unref (user->input_sources); + + user->input_sources = sources; + + if (user->input_sources) + g_variant_ref (user->input_sources); + + save_extra_data (user); + + accounts_user_emit_changed (ACCOUNTS_USER (user)); + + g_object_notify (G_OBJECT (user), "input-sources"); + } + + accounts_user_complete_set_input_sources (ACCOUNTS_USER (user), context); +} + +static gboolean +user_set_input_sources (AccountsUser *auser, + GDBusMethodInvocation *context, + GVariant *sources) +{ + User *user = (User*)auser; + int uid; + const gchar *action_id; + + if (!get_caller_uid (context, &uid)) { + throw_error (context, ERROR_FAILED, "identifying caller failed"); + return FALSE; + } + + if (user->uid == (uid_t) uid) + action_id = "org.freedesktop.accounts.change-own-user-data"; + else + action_id = "org.freedesktop.accounts.user-administration"; + + daemon_local_check_auth (user->daemon, + user, + action_id, + TRUE, + user_change_input_sources_authorized_cb, + context, + sources ? g_variant_ref (sources) : NULL, + sources ? (GDestroyNotify) g_variant_unref : NULL); + + return TRUE; +} + +static void user_change_x_session_authorized_cb (Daemon *daemon, User *user, GDBusMethodInvocation *context, @@ -2926,6 +3111,12 @@ return USER (user)->language; } +static GVariant * +user_real_get_input_sources (AccountsUser *user) +{ + return USER (user)->input_sources; +} + static const gchar * user_real_get_xsession (AccountsUser *user) { @@ -3025,6 +3216,9 @@ if (user->login_history) g_variant_unref (user->login_history); + if (user->input_sources) + g_variant_unref (user->input_sources); + if (G_OBJECT_CLASS (user_parent_class)->finalize) (*G_OBJECT_CLASS (user_parent_class)->finalize) (object); } @@ -3036,6 +3230,7 @@ GParamSpec *pspec) { User *user = USER (object); + GVariant *variant; switch (param_id) { case PROP_ACCOUNT_TYPE: @@ -3047,6 +3242,18 @@ case PROP_FORMATS_LOCALE: user->formats_locale = g_value_dup_string (value); break; + case PROP_INPUT_SOURCES: + variant = g_value_get_variant (value); + + if (variant != user->input_sources) { + if (user->input_sources) + g_variant_unref (user->input_sources); + user->input_sources = variant; + if (user->input_sources) + g_variant_ref (user->input_sources); + } + + break; case PROP_X_SESSION: user->x_session = g_value_dup_string (value); break; @@ -3124,6 +3331,9 @@ else g_value_set_string (value, user_get_fallback_value (user, "FormatsLocale")); break; + case PROP_INPUT_SOURCES: + g_value_set_variant (value, user->input_sources); + break; case PROP_X_SESSION: g_value_set_string (value, user->x_session); break; @@ -3201,6 +3411,7 @@ iface->handle_set_home_directory = user_set_home_directory; iface->handle_set_icon_file = user_set_icon_file; iface->handle_set_language = user_set_language; + iface->handle_set_input_sources = user_set_input_sources; iface->handle_set_location = user_set_location; iface->handle_set_locked = user_set_locked; iface->handle_continue_set_password = user_continue_set_password; @@ -3221,6 +3432,7 @@ iface->get_shell = user_real_get_shell; iface->get_email = user_real_get_email; iface->get_language = user_real_get_language; + iface->get_input_sources = user_real_get_input_sources; iface->get_xsession = user_real_get_xsession; iface->get_location = user_real_get_location; iface->get_login_frequency = user_real_get_login_frequency; @@ -3256,6 +3468,7 @@ user->email = NULL; user->language = NULL; user->formats_locale = NULL; + user->input_sources = NULL; user->x_session = NULL; user->location = NULL; user->password_mode = PASSWORD_MODE_REGULAR; debian/patches/0017-clean-up-cache-dir.patch0000664000000000000000000000314612252421506015551 0ustar Description: Remove user cache files if user account no longer exists Origin: https://launchpad.net/bugs/1259562 Forwarded: https://bugs.freedesktop.org/72596 Author: Gunnar Hjalmarsson Last-Update: 2013-12-12 --- accountsservice-0.6.35.orig/src/daemon.c 2013-10-15 22:25:19.000000000 +0200 +++ accountsservice-0.6.35/src/daemon.c 2013-12-12 21:46:38.187947168 +0100 @@ -374,11 +374,22 @@ g_free (filename); if (regular) { + errno = 0; pwent = getpwnam (name); - if (pwent == NULL) - g_debug ("user '%s' in cache dir but not present on system", name); - else + if (pwent != NULL) return pwent; + else if (errno == 0) { + g_debug ("user '%s' in cache dir but not present on system, removing", name); + filename = g_build_filename (USERDIR, name, NULL); + g_remove (filename); + g_free (filename); + filename = g_build_filename (ICONDIR, name, NULL); + g_remove (filename); + g_free (filename); + } + else + g_warning ("failed to check if user '%s' in cache dir is present on system: %s", + name, g_strerror (errno)); } } debian/patches/1001-buildsystem.patch0000664000000000000000000001650512240704573014576 0ustar 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: debian/patches/git_custom_interfaces.patch0000664000000000000000000005475212240704573016241 0ustar 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 debian/patches/0007-add-lightdm-support.patch0000664000000000000000000002046012266267520016126 0ustar Description: Support setting/reading LightDM autologin setings Author: Michael Terry Bug: https://bugs.freedesktop.org/show_bug.cgi?id=40020 Bug-Ubuntu: https://launchpad.net/bugs/798962 Reviewed-by: Alessio Treglia Last-Update: 2012-04-30 --- src/daemon.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 132 insertions(+), 11 deletions(-) Index: accountsservice-0.6.35/src/daemon.c =================================================================== --- accountsservice-0.6.35.orig/src/daemon.c 2014-01-17 18:57:33.000000000 +0100 +++ accountsservice-0.6.35/src/daemon.c 2014-01-17 18:58:31.480569091 +0100 @@ -51,10 +51,10 @@ #define PATH_SHADOW "/etc/shadow" #define PATH_GROUP "/etc/group" #define PATH_GDM_CUSTOM "/etc/gdm/custom.conf" +#define PATH_LIGHTDM_CONFIG "/etc/lightdm/lightdm.conf" #ifdef HAVE_UTMPX_H #define PATH_WTMP _PATH_WTMPX #endif - enum { PROP_0, PROP_DAEMON_VERSION @@ -72,6 +72,7 @@ GFileMonitor *shadow_monitor; GFileMonitor *group_monitor; GFileMonitor *gdm_monitor; + GFileMonitor *lightdm_monitor; #ifdef HAVE_UTMPX_H GFileMonitor *wtmp_monitor; #endif @@ -703,9 +704,19 @@ on_users_monitor_changed); #endif - daemon->priv->gdm_monitor = setup_monitor (daemon, - PATH_GDM_CUSTOM, - on_gdm_monitor_changed); + if (g_file_test ("/etc/gdm", G_FILE_TEST_EXISTS)) + { + daemon->priv->gdm_monitor = setup_monitor (daemon, + PATH_GDM_CUSTOM, + on_gdm_monitor_changed); + } + + if (g_file_test ("/etc/lightdm", G_FILE_TEST_EXISTS)) + { + daemon->priv->lightdm_monitor = setup_monitor (daemon, + PATH_LIGHTDM_CONFIG, + on_gdm_monitor_changed); + } queue_reload_users (daemon); queue_reload_autologin (daemon); @@ -1435,10 +1446,10 @@ } gboolean -load_autologin (Daemon *daemon, - gchar **name, - gboolean *enabled, - GError **error) +load_autologin_gdm (Daemon *daemon, + gchar **name, + gboolean *enabled, + GError **error) { GKeyFile *keyfile; GError *local_error; @@ -1481,23 +1492,90 @@ return TRUE; } -static gboolean -save_autologin (Daemon *daemon, - const gchar *name, - gboolean enabled, +gboolean +load_autologin_lightdm (Daemon *daemon, + gchar **name, + gboolean *enabled, + GError **error) +{ + GKeyFile *keyfile; + + keyfile = g_key_file_new (); + if (!g_key_file_load_from_file (keyfile, + PATH_LIGHTDM_CONFIG, + G_KEY_FILE_KEEP_COMMENTS, + error)) { + g_key_file_free (keyfile); + return FALSE; + } + + *name = g_key_file_get_string (keyfile, "SeatDefaults", "autologin-user", error); + *enabled = (*error == NULL && (*name) && (*name)[0] != 0); + + g_key_file_free (keyfile); + + return (*error == NULL); +} + +gboolean +load_autologin (Daemon *daemon, + gchar **name, + gboolean *enabled, GError **error) { + GDBusConnection *connection; + GVariant *reply; + + /* First, determine whether we should load GDM or LightDM values by + checking if GDM is running. */ + connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL); + reply = g_dbus_connection_call_sync (connection, + "org.freedesktop.DBus", + "/", + "org.freedesktop.DBus", + "GetNameOwner", + g_variant_new ("(s)", "org.gnome.DisplayManager"), + G_VARIANT_TYPE ("(s)"), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + -1, + NULL, + NULL); + g_object_unref (connection); + + if (reply != NULL) { + g_variant_unref (reply); + return load_autologin_gdm (daemon, name, enabled, error); + } else { + return load_autologin_lightdm (daemon, name, enabled, error); + } +} + +static gboolean +save_autologin_gdm (Daemon *daemon, + const gchar *name, + gboolean enabled, + GError **error) +{ GKeyFile *keyfile; gchar *data; gboolean result; + GError *local_error = NULL; + + if (!g_file_test ("/etc/gdm", G_FILE_TEST_EXISTS)) + return TRUE; /* not an error, just not installed */ keyfile = g_key_file_new (); if (!g_key_file_load_from_file (keyfile, PATH_GDM_CUSTOM, G_KEY_FILE_KEEP_COMMENTS, - error)) { - g_key_file_free (keyfile); - return FALSE; + &local_error)) { + /* It's OK for custom.conf to not exist, we will make it */ + if (!g_error_matches (local_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { + g_propagate_error (error, local_error); + g_key_file_free (keyfile); + return FALSE; + } + g_error_free (local_error); } g_key_file_set_string (keyfile, "daemon", "AutomaticLoginEnable", enabled ? "True" : "False"); @@ -1512,6 +1590,58 @@ return result; } +static gboolean +save_autologin_lightdm (Daemon *daemon, + const gchar *name, + gboolean enabled, + GError **error) +{ + GKeyFile *keyfile; + gchar *data; + gboolean result; + GError *local_error = NULL; + + if (!g_file_test ("/etc/lightdm", G_FILE_TEST_EXISTS)) + return TRUE; /* not an error, just not installed */ + + keyfile = g_key_file_new (); + if (!g_key_file_load_from_file (keyfile, + PATH_LIGHTDM_CONFIG, + G_KEY_FILE_KEEP_COMMENTS, + &local_error)) { + /* It's OK for custom.conf to not exist, we will make it */ + if (!g_error_matches (local_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { + g_propagate_error (error, local_error); + g_key_file_free (keyfile); + return FALSE; + } + g_error_free (local_error); + } + + g_key_file_set_string (keyfile, "SeatDefaults", "autologin-user", enabled ? name : ""); + + data = g_key_file_to_data (keyfile, NULL, NULL); + result = g_file_set_contents (PATH_LIGHTDM_CONFIG, data, -1, error); + + g_key_file_free (keyfile); + g_free (data); + + return result; +} + +static gboolean +save_autologin (Daemon *daemon, + const gchar *name, + gboolean enabled, + GError **error) +{ + if (!save_autologin_gdm (daemon, name, enabled, error)) + return FALSE; + if (!save_autologin_lightdm (daemon, name, enabled, error)) + return FALSE; + return TRUE; +} + gboolean daemon_local_set_automatic_login (Daemon *daemon, User *user, debian/patches/0012-add-keyboard-layout-support.patch0000664000000000000000000003202212240704734017575 0ustar Index: accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml =================================================================== --- accountsservice-0.6.35.orig/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:16:58.756125511 +0100 +++ accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:16:58.744125511 +0100 @@ -331,6 +331,41 @@ + + + + + + The name of the keyboard layouts to use as the user's keyboard layout. The first is the default. + + + + + + + Sets the user's keyboard layouts. + + + + The caller needs one of the following PolicyKit authorizations: + + + org.freedesktop.accounts.change-own-user-data + To change his or her own keyboard layouts + + + org.freedesktop.accounts.user-administration + To change the keyboard layouts of another user + + + + + if the caller lacks the appropriate PolicyKit authorization + if the operation failed + + + + @@ -758,6 +793,16 @@ + + + + + + + The names of the user's keyboard layouts. + + + Index: accountsservice-0.6.35/src/user.c =================================================================== --- accountsservice-0.6.35.orig/src/user.c 2013-11-13 15:16:58.756125511 +0100 +++ accountsservice-0.6.35/src/user.c 2013-11-13 15:16:58.748125511 +0100 @@ -64,6 +64,7 @@ PROP_LOGIN_FREQUENCY, PROP_LOGIN_TIME, PROP_LOGIN_HISTORY, + PROP_X_KEYBOARD_LAYOUTS, PROP_BACKGROUND_FILE, PROP_ICON_FILE, PROP_LOCKED, @@ -99,6 +100,7 @@ gchar *x_session; gchar *location; guint64 login_frequency; + gchar **x_keyboard_layouts; gchar *background_file; gint64 login_time; GVariant *login_history; @@ -371,6 +373,13 @@ g_object_notify (G_OBJECT (user), "password-hint"); } + s = g_key_file_get_string_list (keyfile, "User", "XKeyboardLayouts", NULL, NULL); + if (s != NULL) { + g_strfreev (user->x_keyboard_layouts); + user->x_keyboard_layouts = s; + g_object_notify (G_OBJECT (user), "xkeyboard-layouts"); + } + s = g_key_file_get_string (keyfile, "User", "Background", NULL); if (s != NULL) { g_free (user->background_file); @@ -445,6 +454,9 @@ if (user->password_hint) g_key_file_set_string (keyfile, "User", "PasswordHint", user->password_hint); + if (user->x_keyboard_layouts) + g_key_file_set_string_list (keyfile, "User", "XKeyboardLayouts", (const gchar * const *) user->x_keyboard_layouts, g_strv_length (user->x_keyboard_layouts)); + if (user->background_file) g_key_file_set_string (keyfile, "User", "Background", user->background_file); @@ -1800,6 +1812,55 @@ } static void +user_change_x_keyboard_layouts_authorized_cb (Daemon *daemon, + User *user, + GDBusMethodInvocation *context, + gpointer data) +{ + g_strfreev (user->x_keyboard_layouts); + user->x_keyboard_layouts = g_strdupv (data); + + save_extra_data (user); + + accounts_user_emit_changed (ACCOUNTS_USER (user)); + + g_object_notify (G_OBJECT (user), "xkeyboard-layouts"); + + accounts_user_complete_set_xkeyboard_layouts (ACCOUNTS_USER (user), context); +} + +gboolean +user_set_xkeyboard_layouts (AccountsUser *auser, + GDBusMethodInvocation *context, + const gchar * const *layouts) +{ + User *user = (User*)auser; + int uid; + const gchar *action_id; + + if (!get_caller_uid (context, &uid)) { + throw_error (context, ERROR_FAILED, "identifying caller failed"); + return FALSE; + } + + if (user->uid == (uid_t) uid) + action_id = "org.freedesktop.accounts.change-own-user-data"; + else + action_id = "org.freedesktop.accounts.user-administration"; + + daemon_local_check_auth (user->daemon, + user, + action_id, + TRUE, + user_change_x_keyboard_layouts_authorized_cb, + context, + g_strdupv (layouts), + (GDestroyNotify)g_strfreev); + + return TRUE; +} + +static void user_change_background_file_authorized_cb (Daemon *daemon, User *user, GDBusMethodInvocation *context, @@ -2680,6 +2741,7 @@ g_free (user->real_name); g_free (user->home_dir); g_free (user->shell); + g_strfreev (user->x_keyboard_layouts); g_free (user->icon_file); g_free (user->default_icon_file); g_free (user->background_file); @@ -2798,6 +2860,9 @@ case PROP_LOCATION: g_value_set_string (value, user->location); break; + case PROP_X_KEYBOARD_LAYOUTS: + g_value_set_boxed (value, g_strdupv (user->x_keyboard_layouts)); + break; case PROP_BACKGROUND_FILE: g_value_set_string (value, user->background_file); break; @@ -2870,6 +2935,7 @@ iface->handle_set_real_name = user_set_real_name; iface->handle_set_shell = user_set_shell; iface->handle_set_user_name = user_set_user_name; + iface->handle_set_xkeyboard_layouts = user_set_xkeyboard_layouts; iface->handle_set_xsession = user_set_x_session; iface->get_uid = user_real_get_uid; iface->get_user_name = user_real_get_user_name; @@ -2902,6 +2968,7 @@ user->account_type = ACCOUNT_TYPE_STANDARD; user->home_dir = NULL; user->shell = NULL; + user->x_keyboard_layouts = NULL; user->background_file = NULL; user->icon_file = NULL; user->default_icon_file = NULL; Index: accountsservice-0.6.35/src/libaccountsservice/act-user.c =================================================================== --- accountsservice-0.6.35.orig/src/libaccountsservice/act-user.c 2013-11-13 15:16:58.756125511 +0100 +++ accountsservice-0.6.35/src/libaccountsservice/act-user.c 2013-11-13 15:16:58.752125511 +0100 @@ -91,6 +91,7 @@ PROP_LOGIN_FREQUENCY, PROP_LOGIN_TIME, PROP_LOGIN_HISTORY, + PROP_X_KEYBOARD_LAYOUTS, PROP_BACKGROUND_FILE, PROP_ICON_FILE, PROP_LANGUAGE, @@ -122,6 +123,7 @@ char *shell; char *email; char *location; + char **x_keyboard_layouts; char *background_file; char *icon_file; char *language; @@ -306,6 +308,9 @@ case PROP_LOCATION: g_value_set_string (value, user->location); break; + case PROP_X_KEYBOARD_LAYOUTS: + g_value_set_boxed (value, g_strdupv (user->x_keyboard_layouts)); + break; case PROP_BACKGROUND_FILE: g_value_set_string (value, user->background_file); break; @@ -460,6 +465,13 @@ NULL, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, + PROP_X_KEYBOARD_LAYOUTS, + g_param_spec_boxed ("xkeyboard-layouts", + "Keyboard layouts", + "The name of keyboard layouts for this user.", + G_TYPE_STRV, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, PROP_BACKGROUND_FILE, g_param_spec_string ("background-file", "Background File", @@ -597,6 +609,7 @@ g_free (user->user_name); g_free (user->real_name); + g_strfreev (user->x_keyboard_layouts); g_free (user->background_file); g_free (user->icon_file); g_free (user->language); @@ -1046,6 +1059,22 @@ } /** + * act_user_get_x_keyboard_layouts: + * @user: a #ActUser + * + * Returns the name of the account keyboard layouts belonging to @user. + * + * Returns: (transfer none): names of keyboard layouts + */ +const char * const * +act_user_get_x_keyboard_layouts (ActUser *user) +{ + g_return_val_if_fail (ACT_IS_USER (user), NULL); + + return (const char * const *) user->x_keyboard_layouts; +} + +/** * act_user_get_background_file: * @user: a #ActUser * @@ -1167,6 +1196,28 @@ return user->our_sessions->data; } +static gboolean +strv_equal (const char **a, const char **b) +{ + gint i; + gboolean same = TRUE; + + if (a == b) + return TRUE; + else if (a == NULL || b == NULL) + return FALSE; + + for (i = 0; a[i]; i++) { + if (g_strcmp0 (a[i], b[i]) != 0) + return FALSE; + } + + if (g_strcmp0 (a[i], b[i]) != 0) + return FALSE; + + return TRUE; +} + static void collect_props (const gchar *key, GVariant *value, @@ -1319,6 +1370,15 @@ user->login_history = g_variant_ref (new_login_history); g_object_notify (G_OBJECT (user), "login-history"); } + } else if (strcmp (key, "XKeyboardLayouts") == 0) { + const char **new_x_keyboard_layouts; + + new_x_keyboard_layouts = g_variant_get_strv (value, NULL); + if (!strv_equal (user->x_keyboard_layouts, new_x_keyboard_layouts)) { + g_strfreev (user->x_keyboard_layouts); + user->x_keyboard_layouts = g_strdupv (new_x_keyboard_layouts); + g_object_notify (G_OBJECT (user), "xkeyboard-layouts"); + } } else if (strcmp (key, "BackgroundFile") == 0) { const char *new_background_file; @@ -1681,6 +1741,35 @@ g_error_free (error); return; } +} + +/** + * act_user_set_x_keyboard_layouts: + * @user: the user object to alter. + * @keyboard_layouts: names of keyboard layouts + * + * Assigns a new set of keyboard layouts for @user. + * + * Note this function is synchronous and ignores errors. + **/ +void +act_user_set_x_keyboard_layouts (ActUser *user, + const char * const *keyboard_layouts) +{ + GError *error = NULL; + + g_return_if_fail (ACT_IS_USER (user)); + g_return_if_fail (keyboard_layouts != NULL); + g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy)); + + if (!accounts_user_call_set_xkeyboard_layouts_sync (user->accounts_proxy, + keyboard_layouts, + NULL, + &error)) { + g_warning ("SetXKeyboardLayouts call failed: %s", error->message); + g_error_free (error); + return; + } } /** debian/patches/0005-gdm_config_file_path.patch0000664000000000000000000000205112240704573016333 0ustar Description: Fix path to the GDM configuration file, which is different in Debian. Author: Josselin Mouette Bug-Debian: http://bugs.debian.org/627311 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=49993 --- src/daemon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- accountsservice.orig/src/daemon.c +++ accountsservice/src/daemon.c @@ -49,7 +49,7 @@ #define PATH_SHADOW "/etc/shadow" #define PATH_NOLOGIN "/sbin/nologin" #define PATH_FALSE "/bin/false" -#define PATH_GDM_CUSTOM "/etc/gdm/custom.conf" +#define PATH_GDM_CUSTOM "/etc/gdm3/daemon.conf" static const char *default_excludes[] = { "bin", @@ -611,7 +611,7 @@ reload_autologin_timeout (Daemon *daemon daemon->priv->autologin_id = 0; if (!load_autologin (daemon, &name, &enabled, &error)) { - g_debug ("failed to load gdms custom.conf: %s", error->message); + g_debug ("failed to load gdms daemon.conf: %s", error->message); g_error_free (error); g_free (name); debian/patches/ubuntu.series0000664000000000000000000000102212252033741013347 0ustar 0001-formats-locale-property.patch 0002-create-and-manage-groups-like-on-a-ubuntu-system.patch #0005-gdm_config_file_path.patch 0006-adduser_instead_of_useradd.patch 0007-add-lightdm-support.patch 0008-nopasswdlogin-group.patch 0009-language-tools.patch 0010-set-language.patch 0011-add-background-file-support.patch 0012-add-keyboard-layout-support.patch 0013-add-has-message-support.patch 0014-pam-pin.patch 0015-pam-pin-ubuntu.patch 2002-disable_systemd.patch 0016-add-input-sources-support.patch 0017-clean-up-cache-dir.patch debian/patches/0001-formats-locale-property.patch0000664000000000000000000003372712240704706017026 0ustar Description: Addition of FormatsLocale property and SetFormatsLocale method. Forwarded: https://bugs.freedesktop.org/42857 Author: Gunnar Hjalmarsson Last-Update: 2011-11-12 Index: accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml =================================================================== --- accountsservice-0.6.35.orig/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:16:36.076124828 +0100 +++ accountsservice-0.6.35/data/org.freedesktop.Accounts.User.xml 2013-11-13 15:16:36.064124828 +0100 @@ -150,6 +150,41 @@ + + + + + + The new regional formats, as a locale specification like "de_DE.UTF-8". + + + + + + + Sets the users regional formats. + + + + The caller needs one of the following PolicyKit authorizations: + + + org.freedesktop.accounts.change-own-user-data + To change his own language + + + org.freedesktop.accounts.user-administration + To change the language of another user + + + + + if the caller lacks the appropriate PolicyKit authorization + if the operation failed + + + + @@ -621,6 +656,16 @@ + + + + + + + The users regional formats, as a locale specification like "de_DE.UTF-8". + + + Index: accountsservice-0.6.35/src/libaccountsservice/act-user.c =================================================================== --- accountsservice-0.6.35.orig/src/libaccountsservice/act-user.c 2013-11-13 15:16:36.076124828 +0100 +++ accountsservice-0.6.35/src/libaccountsservice/act-user.c 2013-11-13 15:16:36.068124828 +0100 @@ -93,6 +93,7 @@ PROP_LOGIN_HISTORY, PROP_ICON_FILE, PROP_LANGUAGE, + PROP_FORMATS_LOCALE, PROP_X_SESSION, PROP_IS_LOADED }; @@ -122,6 +123,7 @@ char *location; char *icon_file; char *language; + char *formats_locale; char *x_session; GList *our_sessions; GList *other_sessions; @@ -308,6 +310,9 @@ case PROP_LANGUAGE: g_value_set_string (value, user->language); break; + case PROP_FORMATS_LOCALE: + g_value_set_string (value, user->formats_locale); + break; case PROP_X_SESSION: g_value_set_string (value, user->x_session); break; @@ -464,6 +469,13 @@ NULL, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, + PROP_FORMATS_LOCALE, + g_param_spec_string ("formats_locale", + "Regional Formats", + "User's regional formats.", + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, PROP_X_SESSION, g_param_spec_string ("x-session", "X session", @@ -583,6 +595,7 @@ g_free (user->location); if (user->login_history) g_variant_unref (user->login_history); + g_free (user->formats_locale); if (user->accounts_proxy != NULL) { g_object_unref (user->accounts_proxy); @@ -1052,6 +1065,22 @@ } /** + * act_user_get_formats_locale: + * @user: a #ActUser + * + * Returns the path to the configured formats locale of @user. + * + * Returns: (transfer none): a path to an icon + */ +const char * +act_user_get_formats_locale (ActUser *user) +{ + g_return_val_if_fail (ACT_IS_USER (user), NULL); + + return user->formats_locale; +} + +/** * act_user_get_x_session: * @user: a #ActUser * @@ -1279,6 +1308,17 @@ user->language = g_strdup (new_language); g_object_notify (G_OBJECT (user), "language"); } + + } else if (strcmp (key, "FormatsLocale") == 0) { + const char *new_formats_locale; + + new_formats_locale = g_variant_get_string (value, NULL); + if (g_strcmp0 (user->formats_locale, new_formats_locale) != 0) { + g_free (user->formats_locale); + user->formats_locale = g_strdup (new_formats_locale); + g_object_notify (G_OBJECT (user), "formats_locale"); + } + } else if (strcmp (key, "XSession") == 0) { const char *new_x_session; @@ -1603,6 +1643,35 @@ g_error_free (error); return; } +} + +/** + * act_user_set_formats_locale: + * @user: the user object to alter. + * @formats_locale: a locale (e.g. en_US.utf8) + * + * Assigns a new formats locale for @user. + * + * Note this function is synchronous and ignores errors. + **/ +void +act_user_set_formats_locale (ActUser *user, + const char *formats_locale) +{ + GError *error = NULL; + + g_return_if_fail (ACT_IS_USER (user)); + g_return_if_fail (formats_locale != NULL); + g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy)); + + if (!accounts_user_call_set_formats_locale_sync (user->accounts_proxy, + formats_locale, + NULL, + &error)) { + g_warning ("SetFormatsLocale call failed: %s", error->message); + g_error_free (error); + return; + } } /** Index: accountsservice-0.6.35/src/libaccountsservice/act-user.h =================================================================== --- accountsservice-0.6.35.orig/src/libaccountsservice/act-user.h 2013-11-13 15:16:36.076124828 +0100 +++ accountsservice-0.6.35/src/libaccountsservice/act-user.h 2013-11-13 15:16:36.068124828 +0100 @@ -77,6 +77,7 @@ gboolean act_user_is_nonexistent (ActUser *user); const char *act_user_get_icon_file (ActUser *user); const char *act_user_get_language (ActUser *user); +const char *act_user_get_formats_locale (ActUser *user); const char *act_user_get_x_session (ActUser *user); const char *act_user_get_primary_session_id (ActUser *user); @@ -88,6 +89,8 @@ const char *email); void act_user_set_language (ActUser *user, const char *language); +void act_user_set_formats_locale (ActUser *user, + const char *formats_locale); void act_user_set_x_session (ActUser *user, const char *x_session); void act_user_set_location (ActUser *user, Index: accountsservice-0.6.35/src/user.c =================================================================== --- accountsservice-0.6.35.orig/src/user.c 2013-11-13 15:16:36.076124828 +0100 +++ accountsservice-0.6.35/src/user.c 2013-11-13 15:16:36.072124828 +0100 @@ -58,6 +58,7 @@ PROP_SHELL, PROP_EMAIL, PROP_LANGUAGE, + PROP_FORMATS_LOCALE, PROP_X_SESSION, PROP_LOCATION, PROP_LOGIN_FREQUENCY, @@ -93,6 +94,7 @@ gchar *shell; gchar *email; gchar *language; + gchar *formats_locale; gchar *x_session; gchar *location; guint64 login_frequency; @@ -322,6 +324,13 @@ g_object_notify (G_OBJECT (user), "language"); } + s = g_key_file_get_string (keyfile, "User", "FormatsLocale", NULL); + if (s != NULL) { + g_free (user->formats_locale); + user->formats_locale = s; + g_object_notify (G_OBJECT (user), "formats-locale"); + } + s = g_key_file_get_string (keyfile, "User", "XSession", NULL); if (s != NULL) { g_free (user->x_session); @@ -405,6 +414,9 @@ if (user->language) g_key_file_set_string (keyfile, "User", "Language", user->language); + if (user->formats_locale) + g_key_file_set_string (keyfile, "User", "FormatsLocale", user->formats_locale); + if (user->x_session) g_key_file_set_string (keyfile, "User", "XSession", user->x_session); @@ -1106,6 +1118,61 @@ } static void +user_change_formats_locale_authorized_cb (Daemon *daemon, + User *user, + GDBusMethodInvocation *context, + gpointer data) + +{ + gchar *formats_locale = data; + + if (g_strcmp0 (user->formats_locale, formats_locale) != 0) { + g_free (user->formats_locale); + user->formats_locale = g_strdup (formats_locale); + + save_extra_data (user); + + accounts_user_emit_changed (ACCOUNTS_USER (user)); + + g_object_notify (G_OBJECT (user), "formats_locale"); + } + + accounts_user_complete_set_formats_locale (ACCOUNTS_USER (user), context); +} + +gboolean +user_set_formats_locale (AccountsUser *auser, + GDBusMethodInvocation *context, + const gchar *formats_locale) +{ + User *user = (User*)auser; + + int uid; + const gchar *action_id; + + if (!get_caller_uid (context, &uid)) { + throw_error (context, ERROR_FAILED, "identifying caller failed"); + return FALSE; + } + + if (user->uid == (uid_t) uid) + action_id = "org.freedesktop.accounts.change-own-user-data"; + else + action_id = "org.freedesktop.accounts.user-administration"; + + daemon_local_check_auth (user->daemon, + user, + action_id, + TRUE, + user_change_formats_locale_authorized_cb, + context, + g_strdup (formats_locale), + (GDestroyNotify) g_free); + + return TRUE; +} + +static void user_change_x_session_authorized_cb (Daemon *daemon, User *user, GDBusMethodInvocation *context, @@ -2106,6 +2173,7 @@ g_free (user->default_icon_file); g_free (user->email); g_free (user->language); + g_free (user->formats_locale); g_free (user->x_session); g_free (user->location); g_free (user->password_hint); @@ -2132,6 +2200,9 @@ case PROP_LANGUAGE: user->language = g_value_dup_string (value); break; + case PROP_FORMATS_LOCALE: + user->formats_locale = g_value_dup_string (value); + break; case PROP_X_SESSION: user->x_session = g_value_dup_string (value); break; @@ -2200,6 +2271,9 @@ case PROP_LANGUAGE: g_value_set_string (value, user->language); break; + case PROP_FORMATS_LOCALE: + g_value_set_string (value, user->formats_locale); + break; case PROP_X_SESSION: g_value_set_string (value, user->x_session); break; @@ -2263,6 +2337,7 @@ iface->handle_set_account_type = user_set_account_type; iface->handle_set_automatic_login = user_set_automatic_login; iface->handle_set_email = user_set_email; + iface->handle_set_formats_locale = user_set_formats_locale; iface->handle_set_home_directory = user_set_home_directory; iface->handle_set_icon_file = user_set_icon_file; iface->handle_set_language = user_set_language; @@ -2309,6 +2384,7 @@ user->default_icon_file = NULL; user->email = NULL; user->language = NULL; + user->formats_locale = NULL; user->x_session = NULL; user->location = NULL; user->password_mode = PASSWORD_MODE_REGULAR; debian/accountsservice.prerm0000664000000000000000000000067512240704573013453 0ustar #!/bin/sh set -e get_pid() { [ -n "$1" ] || return 0 [ -S /var/run/dbus/system_bus_socket ] || return 0 dbus-send --system --dest=org.freedesktop.DBus --print-reply \ /org/freedesktop/DBus org.freedesktop.DBus.GetConnectionUnixProcessID \ string:$1 2>/dev/null | awk '/uint32/ {print $2}' } if [ "$1" = "remove" ]; then kill $(get_pid org.freedesktop.Accounts) 2>/dev/null || true fi #DEBHELPER#