From 7d0596956eb79a216b6573b9c9eef5d47292418e Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Wed, 17 Mar 2010 11:56:47 +0100
Subject: [PATCH] Make sss_userdel check for logged in users

sss_userdel now refuses to delete users who are logged in unless --force
is used.

Fixes: #229
---
 src/Makefile.am           |    1 +
 src/man/sss_userdel.8.xml |    4 ++-
 src/tools/sss_userdel.c   |   48 ++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 6d46cda..ae7e403 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -411,6 +411,7 @@ sss_useradd_LDADD = \
 
 sss_userdel_SOURCES = \
     tools/sss_userdel.c \
+    util/find_uid.c \
     $(SSSD_UTIL_OBJ) \
     $(SSSD_TOOLS_OBJ)
 sss_userdel_LDADD = \
diff --git a/src/man/sss_userdel.8.xml b/src/man/sss_userdel.8.xml
index 0c49529..20db8c1 100644
--- a/src/man/sss_userdel.8.xml
+++ b/src/man/sss_userdel.8.xml
@@ -69,7 +69,9 @@
                 </term>
                 <listitem>
                     <para>
-                        This option forces <command>sss_userdel</command>
+                        Forces removal of the user account even if the user is
+                        still logged in.
+                        This option also forces <command>sss_userdel</command>
                         to remove the user's home directory and mail spool,
                         even if they are not owned by the specified user.
                     </para>
diff --git a/src/tools/sss_userdel.c b/src/tools/sss_userdel.c
index e84d78b..227a688 100644
--- a/src/tools/sss_userdel.c
+++ b/src/tools/sss_userdel.c
@@ -26,9 +26,32 @@
 
 #include "db/sysdb.h"
 #include "util/util.h"
+#include "util/find_uid.h"
 #include "tools/tools_util.h"
 #include "tools/sss_sync_ops.h"
 
+static int is_logged_in(TALLOC_CTX *mem_ctx, uid_t uid)
+{
+    int ret;
+    hash_key_t key;
+    hash_value_t value;
+    hash_table_t *uid_table;
+
+    ret = get_uid_table(mem_ctx, &uid_table);
+    if (ret == ENOSYS) return ret;
+    if (ret != EOK) {
+        DEBUG(1, ("Cannot initialize hash table.\n"));
+        return ret;
+    }
+
+    key.type = HASH_KEY_ULONG;
+    key.ul   = (unsigned long) uid;
+
+    ret = hash_lookup(uid_table, &key, &value);
+    talloc_zfree(uid_table);
+    return ret == HASH_SUCCESS ? EOK : ENOENT;
+}
+
 int main(int argc, const char **argv)
 {
     int ret = EXIT_SUCCESS;
@@ -43,9 +66,13 @@ int main(int argc, const char **argv)
         POPT_AUTOHELP
         { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug,
                     0, _("The debug level to run with"), NULL },
-        { "remove", 'r', POPT_ARG_NONE, NULL, 'r', _("Remove home directory and mail spool"), NULL },
-        { "no-remove", 'R', POPT_ARG_NONE, NULL, 'R', _("Do not remove home directory and mail spool"), NULL },
-        { "force", 'f', POPT_ARG_NONE, NULL, 'f', _("Force removal of files not owned by the user"), NULL },
+        { "remove", 'r', POPT_ARG_NONE, NULL, 'r',
+                    _("Remove home directory and mail spool"), NULL },
+        { "no-remove", 'R', POPT_ARG_NONE, NULL, 'R',
+                    _("Do not remove home directory and mail spool"), NULL },
+        { "force", 'f', POPT_ARG_NONE, NULL, 'f',
+                    _("Force removal of user if logged in and/or removal of "
+                      "files not owned by the user"), NULL },
         POPT_TABLEEND
     };
 
@@ -136,6 +163,21 @@ int main(int argc, const char **argv)
         goto done;
     }
 
+    ret = is_logged_in(tctx, tctx->octx->uid);
+    if (!pc_force && ret != ENOENT) {
+        if (ret == EOK) {
+            ERROR("Cannot delete - the user is still logged in. You can use "
+                  "the --force switch to override this check\n");
+            goto done;
+        } else if (ret == ENOSYS) {
+            ERROR("WARNING: Cannot determine if the user is logged in or not "
+                  "on this platform\n");
+        } else {
+            ERROR("Error while checking if the user is logged in\n");
+            goto done;
+        }
+    }
+
     if ((tctx->octx->uid < tctx->local->id_min) ||
         (tctx->local->id_max && tctx->octx->uid > tctx->local->id_max)) {
         ERROR("User %s is outside the defined ID range for domain\n",
-- 
1.6.6.1

