|
|
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 |
|