From 51aad40a82b82009e7b0a7d13220c0dc658c4ab6 Mon Sep 17 00:00:00 2001 From: Imran Zaman Date: Wed, 20 Aug 2014 15:39:03 +0300 Subject: [PATCH] Added support for scripts which can be run after a user/group is added or before a user/group is deleted --- dists/debian/changelog | 7 ++ dists/debian/gumd.install | 2 +- dists/debian/gumd.postinst | 4 + dists/rpm/gum-suse.spec | 12 ++- dists/rpm/tizen/packaging/gumd.changes | 4 + dists/rpm/tizen/packaging/gumd.spec | 15 ++- include/gum/common/gum-config-general.h | 2 +- include/gum/common/gum-utils.h | 15 +++ src/common/gum-utils.c | 184 ++++++++++++++++++++++++++++++++ src/daemon/Makefile.am | 7 +- src/daemon/gumd-daemon-group.c | 23 ++++ src/daemon/gumd-daemon-user.c | 23 ++++ test/data/groupadd.d/group_add.sh | 5 + test/data/groupdel.d/group_del.sh | 5 + test/data/gumd.conf | 4 +- test/data/useradd.d/user_add.sh | 5 + test/data/userdel.d/user_del.sh | 5 + test/lib/Makefile.am | 6 +- 18 files changed, 315 insertions(+), 13 deletions(-) create mode 100755 test/data/groupadd.d/group_add.sh create mode 100755 test/data/groupdel.d/group_del.sh create mode 100755 test/data/useradd.d/user_add.sh create mode 100755 test/data/userdel.d/user_del.sh diff --git a/dists/debian/changelog b/dists/debian/changelog index ef3fe56..3ba5db5 100644 --- a/dists/debian/changelog +++ b/dists/debian/changelog @@ -1,3 +1,10 @@ +gumd (0.0.4-2) unstable; urgency=low + + * Added support for scripts which can be run after a user/group is added + or before a user/group is deleted + + -- Imran Zaman Thu, 21 Aug 2014 16:31:03 +0300 + gumd (0.0.4-1) unstable; urgency=low * Fix access permissions for user home directory diff --git a/dists/debian/gumd.install b/dists/debian/gumd.install index 10c9484..86e44ce 100644 --- a/dists/debian/gumd.install +++ b/dists/debian/gumd.install @@ -1,4 +1,4 @@ /usr/bin/gumd -/etc/gumd.conf +/etc/gumd/gumd.conf /usr/share/dbus-1/system-services/*UserManagement*.service /etc/dbus-1/system.d/gumd-dbus.conf diff --git a/dists/debian/gumd.postinst b/dists/debian/gumd.postinst index d37006e..89ac13b 100644 --- a/dists/debian/gumd.postinst +++ b/dists/debian/gumd.postinst @@ -23,6 +23,10 @@ case "$1" in ldconfig groupadd -f -r gumd chmod 4755 /usr/bin/gumd + mkdir -p /etc/gumd/useradd.d + mkdir -p /etc/gumd/userdel.d + mkdir -p /etc/gumd/groupadd.d + mkdir -p /etc/gumd/groupdel.d ;; abort-upgrade|abort-remove|abort-deconfigure) diff --git a/dists/rpm/gum-suse.spec b/dists/rpm/gum-suse.spec index 0587a0f..1a51589 100644 --- a/dists/rpm/gum-suse.spec +++ b/dists/rpm/gum-suse.spec @@ -8,7 +8,7 @@ Name: gumd Summary: User management daemon and client library Version: 0.0.4 -Release: 1 +Release: 2 Group: System/Daemons License: LGPL-2.1+ Source: %{name}-%{version}.tar.gz @@ -86,6 +86,10 @@ rm -rf %{buildroot} /sbin/ldconfig chmod u+s %{_bindir}/%{name} groupadd -f -r gumd +mkdir -p %{_sysconfdir}/%{name}/useradd.d +mkdir -p %{_sysconfdir}/%{name}/userdel.d +mkdir -p %{_sysconfdir}/%{name}/groupadd.d +mkdir -p %{_sysconfdir}/%{name}/groupdel.d %postun -p /sbin/ldconfig @@ -112,7 +116,7 @@ groupadd -f -r gumd %defattr(-,root,root,-) %doc AUTHORS COPYING.LIB INSTALL NEWS README %{_bindir}/%{name} -%config(noreplace) %{_sysconfdir}/gumd.conf +%config(noreplace) %{_sysconfdir}/%{name}/gumd.conf %if %{dbus_type} == "session" %dir %{_datadir}/dbus-1/services %{_datadir}/dbus-1/services/*UserManagement*.service @@ -131,6 +135,10 @@ groupadd -f -r gumd %changelog +* Thu Aug 21 2014 Imran Zaman +- Added support for scripts which can be run after a user/group is added + or before a user/group is deleted + * Tue Aug 12 2014 Imran Zaman - Fix access permissions for user home directory diff --git a/dists/rpm/tizen/packaging/gumd.changes b/dists/rpm/tizen/packaging/gumd.changes index 605930e..ec322a6 100644 --- a/dists/rpm/tizen/packaging/gumd.changes +++ b/dists/rpm/tizen/packaging/gumd.changes @@ -1,3 +1,7 @@ +* Thu Aug 21 2014 Imran Zaman +- Added support for scripts which can be run after a user/group is added + or before a user/group is deleted + * Tue Aug 12 2014 Imran Zaman - Fix access permissions for user home directory diff --git a/dists/rpm/tizen/packaging/gumd.spec b/dists/rpm/tizen/packaging/gumd.spec index 7782825..0bf5209 100644 --- a/dists/rpm/tizen/packaging/gumd.spec +++ b/dists/rpm/tizen/packaging/gumd.spec @@ -7,7 +7,7 @@ Name: gumd Summary: User management daemon and client library Version: 0.0.4 -Release: 1 +Release: 2 Group: Security/Accounts License: LGPL-2.1+ Source: %{name}-%{version}.tar.gz @@ -85,13 +85,17 @@ rm -rf %{buildroot} %make_install cp -a %{SOURCE1001} %{buildroot}%{_datadir}/%{name}.manifest cp -a %{SOURCE1002} %{buildroot}%{_datadir}/libgum.manifest -cp -a %{SOURCE1003} %{buildroot}%{_sysconfdir}/%{name}.conf +cp -a %{SOURCE1003} %{buildroot}%{_sysconfdir}/%{name}/%{name}.conf %post /sbin/ldconfig -chmod u+s %{_bindir}/%{name} -getent group gumd > /dev/null || /usr/sbin/groupadd -r gumd +/usr/bin/chmod u+s %{_bindir}/%{name} +/usr/bin/getent group gumd > /dev/null || /usr/sbin/groupadd -r gumd +/usr/bin/mkdir -p %{_sysconfdir}/%{name}/useradd.d +/usr/bin/mkdir -p %{_sysconfdir}/%{name}/userdel.d +/usr/bin/mkdir -p %{_sysconfdir}/%{name}/groupadd.d +/usr/bin/mkdir -p %{_sysconfdir}/%{name}/groupdel.d %postun -p /sbin/ldconfig @@ -119,7 +123,8 @@ getent group gumd > /dev/null || /usr/sbin/groupadd -r gumd %manifest %{_datadir}/%{name}.manifest %doc AUTHORS COPYING.LIB INSTALL NEWS README %{_bindir}/%{name} -%config(noreplace) %{_sysconfdir}/%{name}.conf +%dir %{_sysconfdir}/%{name} +%config(noreplace) %{_sysconfdir}/%{name}/%{name}.conf %if %{dbus_type} == "session" %dir %{_datadir}/dbus-1/services %{_datadir}/dbus-1/services/*UserManagement*.service diff --git a/include/gum/common/gum-config-general.h b/include/gum/common/gum-config-general.h index bda7614..3d0d6f0 100644 --- a/include/gum/common/gum-config-general.h +++ b/include/gum/common/gum-config-general.h @@ -245,7 +245,7 @@ * GUM_CONFIG_GENERAL_UMASK: * * Value used to set the mode of home directories created for new users. - * Default value is: 022 + * Default value is: 077 */ #define GUM_CONFIG_GENERAL_UMASK GUM_CONFIG_GENERAL \ "/UMASK" diff --git a/include/gum/common/gum-utils.h b/include/gum/common/gum-utils.h index 00301eb..a6d1caf 100644 --- a/include/gum/common/gum-utils.h +++ b/include/gum/common/gum-utils.h @@ -28,6 +28,7 @@ #define _GUM_UTILS_H_ #include +#include G_BEGIN_DECLS @@ -41,6 +42,20 @@ gum_utils_drop_privileges (); void gum_utils_gain_privileges (); +gboolean +gum_utils_run_user_scripts ( + const gchar *script_dir, + const gchar *username, + uid_t uid, + gid_t gid, + const gchar *homedir); + +gboolean +gum_utils_run_group_scripts ( + const gchar *script_dir, + const gchar *groupname, + gid_t gid); + G_END_DECLS #endif /* _GUM_UTILS_H_ */ diff --git a/src/common/gum-utils.c b/src/common/gum-utils.c index 9e468ac..5db5d8f 100644 --- a/src/common/gum-utils.c +++ b/src/common/gum-utils.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include "common/gum-utils.h" #include "common/gum-log.h" @@ -154,3 +156,185 @@ gum_utils_gain_privileges () WARN ("seteuid() failed"); DBG ("After set: r-uid %d e-uid %d", getuid (), geteuid ()); } + +static gint +_script_sort ( + gconstpointer a, + gconstpointer b, + gpointer data) +{ + (void)data; + return g_strcmp0 ((const gchar *) a, (const gchar *) b); +} + +void +_run_script (const gchar *script_dir, + gchar **args) +{ + gint status; + gboolean ret = FALSE; + const gchar *script = args[0]; + GError *error = NULL; + + if (!script || + !g_file_test(script, G_FILE_TEST_EXISTS)) { + DBG ("script file does not exist: %s", script); + return; + } + + ret = g_spawn_sync (NULL, args, NULL, + G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, NULL, + NULL, NULL, NULL, &status, &error); + if (!ret) { + WARN ("g_spawn failed as retval %d and status %d", ret, status); + } + if (error) { + WARN ("script failed with error %s", error->message); + g_error_free (error); + } +} + +gboolean +_run_scripts ( + const gchar *script_dir, + gchar **args) +{ + GDir *dir = NULL; + const gchar *script_fname = NULL; + gchar *script_filepath = NULL; + struct stat stat_entry; + GSequence *scripts = NULL; + GSequenceIter *scripts_iter = NULL; + gboolean stop = FALSE; + + DBG (""); + + if (!script_dir || + !g_file_test(script_dir, G_FILE_TEST_EXISTS) || + !g_file_test (script_dir, G_FILE_TEST_IS_DIR)) { + DBG ("script dir check failed %s", script_dir); + g_strfreev (args); + return FALSE; + } + dir = g_dir_open (script_dir, 0, NULL); + if (!dir) { + DBG ("unable to open script dir %s", script_dir); + g_strfreev (args); + return FALSE; + } + + scripts = g_sequence_new ((GDestroyNotify) g_free); + while ((script_fname = g_dir_read_name (dir))) { + if (g_strcmp0 (script_fname, ".") == 0 || + g_strcmp0 (script_fname, "..") == 0) { + continue; + } + script_filepath = g_build_filename (script_dir, script_fname, NULL); + stop = (lstat(script_filepath, &stat_entry) != 0); + if (stop) goto _free_data; + + if (!S_ISDIR (stat_entry.st_mode)) { + DBG ("insert script file %s", script_filepath); + g_sequence_insert_sorted (scripts, + (gpointer) script_filepath, + _script_sort, + NULL); + script_filepath = NULL; + } + +_free_data: + g_free (script_filepath); + if (stop) { + WARN ("failure in reading script dir %s", script_dir); + g_sequence_free (scripts); + scripts = NULL; + break; + } + } + g_dir_close (dir); + + if (!scripts) { + g_strfreev (args); + return FALSE; + } + + gchar* tmp = args[0]; + scripts_iter = g_sequence_get_begin_iter (scripts); + while (!g_sequence_iter_is_end (scripts_iter)) { + args[0] = (gchar *)g_sequence_get (scripts_iter); + _run_script (script_dir, args); + scripts_iter = g_sequence_iter_next (scripts_iter); + } + args[0] = tmp; + g_sequence_free (scripts); + g_strfreev (args); + return TRUE; +} + +/** + * gum_utils_run_user_scripts: + * @script_dir: path to the scripts directory + * @username: name of the user + * @uid: uid of the user + * @gid: gid of the user + * @homedir: home directory of the user + * + * Runs the user scripts in sorted order. + * + * Returns: TRUE if successful, FALSE otherwise + */ +gboolean +gum_utils_run_user_scripts ( + const gchar *script_dir, + const gchar *username, + uid_t uid, + gid_t gid, + const gchar *homedir) +{ + gchar **args = NULL; + DBG (""); + + if (!username || !homedir) { + DBG ("script invalid username/homedir for script dir"); + return FALSE; + } + args = g_new0 (gchar *, 6); + args[0] = g_strdup (""); /* script path to be added later on */ + args[1] = g_strdup (username); + args[2] = g_strdup_printf ("%u", uid); + args[3] = g_strdup_printf ("%u", gid); + args[4] = g_strdup (homedir); + /* ownership of 'args' is transferred to _run_scripts */ + return _run_scripts (script_dir, args);; +} + +/** + * gum_utils_run_group_scripts: + * @script_dir: path to the scripts directory + * @groupname: name of the group + * @gid: gid of the group + * + * Runs the group scripts in sorted order. + * + * Returns: TRUE if successful, FALSE otherwise + */ +gboolean +gum_utils_run_group_scripts ( + const gchar *script_dir, + const gchar *groupname, + gid_t gid) +{ + gchar **args = NULL; + DBG (""); + + if (!groupname) { + DBG ("script invalid groupname for script dir"); + return FALSE; + } + args = g_new0 (gchar *, 4); + args[0] = g_strdup (""); /* script path to be added later on */ + args[1] = g_strdup (groupname); + args[2] = g_strdup_printf ("%u", gid); + /* ownership of 'args' is transferred to _run_scripts */ + return _run_scripts (script_dir, args);; +} diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am index 262920e..4224b88 100644 --- a/src/daemon/Makefile.am +++ b/src/daemon/Makefile.am @@ -18,6 +18,10 @@ gumd_CFLAGS = \ $(GUMD_INCLUDES) \ $(GUMD_CFLAGS) \ -I$(top_srcdir)/src \ + -DUSERADD_SCRIPT_DIR='"${sysconfdir}/gumd/useradd.d"' \ + -DUSERDEL_SCRIPT_DIR='"${sysconfdir}/gumd/userdel.d"' \ + -DGROUPADD_SCRIPT_DIR='"${sysconfdir}/gumd/groupadd.d"' \ + -DGROUPDEL_SCRIPT_DIR='"${sysconfdir}/gumd/groupdel.d"' \ $(NULL) gumd_LDADD = \ @@ -29,7 +33,8 @@ gumd_LDADD = \ EXTRA_DIST = \ gumd.conf.in -sysconf_DATA = gumd.conf +gumdconfdir = ${sysconfdir}/gumd +gumdconf_DATA = gumd.conf if SET_PERMISSIONS install-exec-hook: diff --git a/src/daemon/gumd-daemon-group.c b/src/daemon/gumd-daemon-group.c index 51785ea..226a225 100644 --- a/src/daemon/gumd-daemon-group.c +++ b/src/daemon/gumd-daemon-group.c @@ -22,6 +22,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ +#include "config.h" + #include #include #include @@ -37,6 +39,7 @@ #include "common/gum-defines.h" #include "common/gum-log.h" #include "common/gum-error.h" +#include "common/gum-utils.h" struct _GumdDaemonGroupPrivate { @@ -866,6 +869,16 @@ gumd_daemon_group_add ( *gid = self->priv->group->gr_gid; } + const gchar *scrip_dir = GROUPADD_SCRIPT_DIR; +# ifdef ENABLE_DEBUG + const gchar *env_val = g_getenv("UM_GROUPADD_DIR"); + if (env_val) + scrip_dir = env_val; +# endif + + gum_utils_run_group_scripts (scrip_dir, self->priv->group->gr_name, + self->priv->group->gr_gid); + gum_lock_pwdf_unlock (); return TRUE; } @@ -912,6 +925,16 @@ gumd_daemon_group_delete ( "Group is a primary group of an existing user", error, FALSE); } + const gchar *scrip_dir = GROUPDEL_SCRIPT_DIR; +# ifdef ENABLE_DEBUG + const gchar *env_val = g_getenv("UM_GROUPDEL_DIR"); + if (env_val) + scrip_dir = env_val; +# endif + + gum_utils_run_group_scripts (scrip_dir, self->priv->group->gr_name, + self->priv->group->gr_gid); + if (!gum_file_update (G_OBJECT (self), GUM_OPTYPE_DELETE, (GumFileUpdateCB)_update_daemon_group_entry, gum_config_get_string (self->priv->config, diff --git a/src/daemon/gumd-daemon-user.c b/src/daemon/gumd-daemon-user.c index f4e4bb6..f256cce 100644 --- a/src/daemon/gumd-daemon-user.c +++ b/src/daemon/gumd-daemon-user.c @@ -43,6 +43,7 @@ #include "common/gum-defines.h" #include "common/gum-log.h" #include "common/gum-error.h" +#include "common/gum-utils.h" struct _GumdDaemonUserPrivate { @@ -1515,6 +1516,17 @@ gumd_daemon_user_add ( *uid = self->priv->pw->pw_uid; } + const gchar *scrip_dir = USERADD_SCRIPT_DIR; +# ifdef ENABLE_DEBUG + const gchar *env_val = g_getenv("UM_USERADD_DIR"); + if (env_val) + scrip_dir = env_val; +# endif + + gum_utils_run_user_scripts (scrip_dir, self->priv->pw->pw_name, + self->priv->pw->pw_uid, self->priv->pw->pw_gid, + self->priv->pw->pw_dir); + gum_lock_pwdf_unlock (); return TRUE; } @@ -1583,6 +1595,17 @@ gumd_daemon_user_delete ( "unable to terminate user active sessions", error, FALSE); } + const gchar *scrip_dir = USERDEL_SCRIPT_DIR; +# ifdef ENABLE_DEBUG + const gchar *env_val = g_getenv("UM_USERDEL_DIR"); + if (env_val) + scrip_dir = env_val; +# endif + + gum_utils_run_user_scripts (scrip_dir, self->priv->pw->pw_name, + self->priv->pw->pw_uid, self->priv->pw->pw_gid, + self->priv->pw->pw_dir); + if (!gum_file_update (G_OBJECT (self), GUM_OPTYPE_DELETE, (GumFileUpdateCB)_update_passwd_entry, gum_config_get_string (self->priv->config, diff --git a/test/data/groupadd.d/group_add.sh b/test/data/groupadd.d/group_add.sh new file mode 100755 index 0000000..9afdadc --- /dev/null +++ b/test/data/groupadd.d/group_add.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +echo "New group $1($2) is added" + + diff --git a/test/data/groupdel.d/group_del.sh b/test/data/groupdel.d/group_del.sh new file mode 100755 index 0000000..9964462 --- /dev/null +++ b/test/data/groupdel.d/group_del.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +echo "Group $1($2) is about to be deleted" + + diff --git a/test/data/gumd.conf b/test/data/gumd.conf index 325554c..bfe1fa8 100644 --- a/test/data/gumd.conf +++ b/test/data/gumd.conf @@ -100,8 +100,8 @@ DEFAULT_USR_GROUPS= #PASS_WARN_AGE=7 # Value used to set the mode of home directories created for new users. -# Default value is: 022 -#UMASK=022 +# Default value is: 077 +#UMASK=077 # Value used to set the encryption algorithm. Default # value is: 'SHA512' (other supported options are: 'MD5', 'SHA256', 'DES') diff --git a/test/data/useradd.d/user_add.sh b/test/data/useradd.d/user_add.sh new file mode 100755 index 0000000..8f1f9af --- /dev/null +++ b/test/data/useradd.d/user_add.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +echo "New user $1($2) is added" + + diff --git a/test/data/userdel.d/user_del.sh b/test/data/userdel.d/user_del.sh new file mode 100755 index 0000000..4632e68 --- /dev/null +++ b/test/data/userdel.d/user_del.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +echo "User $1($2) is about to be deleted" + + diff --git a/test/lib/Makefile.am b/test/lib/Makefile.am index 1b9847e..90aca58 100644 --- a/test/lib/Makefile.am +++ b/test/lib/Makefile.am @@ -2,7 +2,11 @@ include $(top_srcdir)/test/test_common.mk TESTS = clienttest TESTS_ENVIRONMENT += \ - UM_BIN_DIR=$(top_builddir)/src/daemon/.libs + UM_BIN_DIR=$(top_builddir)/src/daemon/.libs \ + UM_USERADD_DIR=$(abs_top_srcdir)/test/data/useradd.d \ + UM_USERDEL_DIR=$(abs_top_srcdir)/test/data/userdel.d \ + UM_GROUPADD_DIR=$(abs_top_srcdir)/test/data/groupadd.d \ + UM_GROUPDEL_DIR=$(abs_top_srcdir)/test/data/groupdel.d VALGRIND_TESTS_DISABLE= -- 2.7.4