Blame SOURCES/0001-user-classify-exclude-nologin-users.patch

44ca26
From 450731558cbd5c77aa6932d35f27abf898553db6 Mon Sep 17 00:00:00 2001
44ca26
From: Ray Strode <rstrode@redhat.com>
44ca26
Date: Tue, 6 Sep 2016 13:54:48 -0400
44ca26
Subject: [PATCH] user-classify: exclude nologin users
44ca26
44ca26
Sometimes admins set a user's shell to nologin to hide it from
44ca26
the user list.  This commit fixes accountsservice so that behavior
44ca26
works again.
44ca26
---
44ca26
 src/user-classify.c | 77 +++++++++++++++++++++++++++++------------------------
44ca26
 1 file changed, 42 insertions(+), 35 deletions(-)
44ca26
44ca26
diff --git a/src/user-classify.c b/src/user-classify.c
44ca26
index 69e6809..b79a35f 100644
44ca26
--- a/src/user-classify.c
44ca26
+++ b/src/user-classify.c
44ca26
@@ -1,169 +1,176 @@
44ca26
 /*
44ca26
  * Copyright (C) 2009-2010 Red Hat, Inc.
44ca26
  * Copyright (C) 2013 Canonical Limited
44ca26
  *
44ca26
  * This program is free software; you can redistribute it and/or modify
44ca26
  * it under the terms of the GNU General Public License as published by
44ca26
  * the Free Software Foundation; either version 3 of the licence, or
44ca26
  * (at your option) any later version.
44ca26
  *
44ca26
  * This program is distributed in the hope that it will be useful,
44ca26
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
44ca26
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
44ca26
  * GNU General Public License for more details.
44ca26
  *
44ca26
  * You should have received a copy of the GNU General Public License
44ca26
  * along with this program; if not, write to the Free Software
44ca26
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
44ca26
  *
44ca26
  * Authors: Ryan Lortie <desrt@desrt.ca>
44ca26
  *          Matthias Clasen <mclasen@redhat.com>
44ca26
  */
44ca26
 
44ca26
 #include "config.h"
44ca26
 
44ca26
 #include "user-classify.h"
44ca26
 
44ca26
 #include <string.h>
44ca26
+#include <unistd.h>
44ca26
 
44ca26
 static const char *default_excludes[] = {
44ca26
         "bin",
44ca26
         "root",
44ca26
         "daemon",
44ca26
         "adm",
44ca26
         "lp",
44ca26
         "sync",
44ca26
         "shutdown",
44ca26
         "halt",
44ca26
         "mail",
44ca26
         "news",
44ca26
         "uucp",
44ca26
         "operator",
44ca26
         "nobody",
44ca26
         "nobody4",
44ca26
         "noaccess",
44ca26
         "postgres",
44ca26
         "pvm",
44ca26
         "rpm",
44ca26
         "nfsnobody",
44ca26
         "pcap",
44ca26
         "mysql",
44ca26
         "ftp",
44ca26
         "games",
44ca26
         "man",
44ca26
         "at",
44ca26
         "gdm",
44ca26
         "gnome-initial-setup"
44ca26
 };
44ca26
 
44ca26
 static gboolean
44ca26
 user_classify_is_blacklisted (const char *username)
44ca26
 {
44ca26
         static GHashTable *exclusions;
44ca26
 
44ca26
         if (exclusions == NULL) {
44ca26
                 guint i;
44ca26
 
44ca26
                 exclusions = g_hash_table_new (g_str_hash, g_str_equal);
44ca26
 
44ca26
                 for (i = 0; i < G_N_ELEMENTS (default_excludes); i++) {
44ca26
                         g_hash_table_add (exclusions, (gpointer) default_excludes[i]);
44ca26
                 }
44ca26
         }
44ca26
 
44ca26
         if (g_hash_table_contains (exclusions, username)) {
44ca26
                 return TRUE;
44ca26
         }
44ca26
 
44ca26
         return FALSE;
44ca26
 }
44ca26
 
44ca26
 #define PATH_NOLOGIN "/sbin/nologin"
44ca26
 #define PATH_FALSE "/bin/false"
44ca26
 
44ca26
 #ifdef ENABLE_USER_HEURISTICS
44ca26
 static gboolean
44ca26
 user_classify_is_excluded_by_heuristics (const gchar *username,
44ca26
-                                         const gchar *shell,
44ca26
                                          const gchar *password_hash)
44ca26
 {
44ca26
         gboolean ret = FALSE;
44ca26
 
44ca26
-        if (shell != NULL) {
44ca26
-                char *basename, *nologin_basename, *false_basename;
44ca26
-
44ca26
-#ifdef HAVE_GETUSERSHELL
44ca26
-                char *valid_shell;
44ca26
-
44ca26
-                ret = TRUE;
44ca26
-                setusershell ();
44ca26
-                while ((valid_shell = getusershell ()) != NULL) {
44ca26
-                        if (g_strcmp0 (shell, valid_shell) != 0)
44ca26
-                                continue;
44ca26
-                        ret = FALSE;
44ca26
-                }
44ca26
-                endusershell ();
44ca26
-#endif
44ca26
-
44ca26
-                basename = g_path_get_basename (shell);
44ca26
-                nologin_basename = g_path_get_basename (PATH_NOLOGIN);
44ca26
-                false_basename = g_path_get_basename (PATH_FALSE);
44ca26
-
44ca26
-                if (shell[0] == '\0') {
44ca26
-                        ret = TRUE;
44ca26
-                } else if (g_strcmp0 (basename, nologin_basename) == 0) {
44ca26
-                        ret = TRUE;
44ca26
-                } else if (g_strcmp0 (basename, false_basename) == 0) {
44ca26
-                        ret = TRUE;
44ca26
-                }
44ca26
-
44ca26
-                g_free (basename);
44ca26
-                g_free (nologin_basename);
44ca26
-                g_free (false_basename);
44ca26
-        }
44ca26
-
44ca26
         if (password_hash != NULL) {
44ca26
                 /* skip over the account-is-locked '!' prefix if present */
44ca26
                 if (password_hash[0] == '!')
44ca26
                     password_hash++;
44ca26
 
44ca26
                 if (password_hash[0] != '\0') {
44ca26
                         /* modern hashes start with "$n$" */
44ca26
                         if (password_hash[0] == '$') {
44ca26
                                 if (strlen (password_hash) < 4)
44ca26
                                     ret = TRUE;
44ca26
 
44ca26
                         /* DES crypt is base64 encoded [./A-Za-z0-9]*
44ca26
                          */
44ca26
                         } else if (!g_ascii_isalnum (password_hash[0]) &&
44ca26
                                    password_hash[0] != '.' &&
44ca26
                                    password_hash[0] != '/') {
44ca26
                                 ret = TRUE;
44ca26
                         }
44ca26
                 }
44ca26
 
44ca26
         }
44ca26
 
44ca26
         return ret;
44ca26
 }
44ca26
 #endif /* ENABLE_USER_HEURISTICS */
44ca26
 
44ca26
+static gboolean
44ca26
+is_invalid_shell (const char *shell)
44ca26
+{
44ca26
+        char *basename, *nologin_basename, *false_basename;
44ca26
+        int ret = FALSE;
44ca26
+
44ca26
+#ifdef HAVE_GETUSERSHELL
44ca26
+        char *valid_shell;
44ca26
+
44ca26
+        setusershell ();
44ca26
+        while ((valid_shell = getusershell ()) != NULL) {
44ca26
+                if (g_strcmp0 (shell, valid_shell) != 0)
44ca26
+                        continue;
44ca26
+                ret = FALSE;
44ca26
+        }
44ca26
+        endusershell ();
44ca26
+#endif
44ca26
+
44ca26
+        basename = g_path_get_basename (shell);
44ca26
+        nologin_basename = g_path_get_basename (PATH_NOLOGIN);
44ca26
+        false_basename = g_path_get_basename (PATH_FALSE);
44ca26
+
44ca26
+        if (shell[0] == '\0') {
44ca26
+                ret = TRUE;
44ca26
+        } else if (g_strcmp0 (basename, nologin_basename) == 0) {
44ca26
+                ret = TRUE;
44ca26
+        } else if (g_strcmp0 (basename, false_basename) == 0) {
44ca26
+                ret = TRUE;
44ca26
+        }
44ca26
+
44ca26
+        g_free (basename);
44ca26
+        g_free (nologin_basename);
44ca26
+        g_free (false_basename);
44ca26
+
44ca26
+        return ret;
44ca26
+}
44ca26
+
44ca26
 gboolean
44ca26
 user_classify_is_human (uid_t        uid,
44ca26
                         const gchar *username,
44ca26
                         const gchar *shell,
44ca26
                         const gchar *password_hash)
44ca26
 {
44ca26
         if (user_classify_is_blacklisted (username))
44ca26
                 return FALSE;
44ca26
 
44ca26
+        if (shell != NULL && is_invalid_shell (shell))
44ca26
+                return FALSE;
44ca26
+
44ca26
 #ifdef ENABLE_USER_HEURISTICS
44ca26
         /* only do heuristics on the range 500-1000 to catch one off migration problems in Fedora */
44ca26
         if (uid >= 500 && uid < MINIMUM_UID) {
44ca26
-                if (!user_classify_is_excluded_by_heuristics (username, shell, password_hash))
44ca26
+                if (!user_classify_is_excluded_by_heuristics (username, password_hash))
44ca26
                         return TRUE;
44ca26
         }
44ca26
 #endif
44ca26
 
44ca26
         return uid >= MINIMUM_UID;
44ca26
 }
44ca26
-- 
44ca26
2.7.4
44ca26