From 32464b4c0d120ea82686fc3cdf9bc24ce327e1bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sven=20M=C3=A4der?= <maeder@phys.ethz.ch>
Date: Thu, 23 Aug 2018 17:15:29 +0200
Subject: [PATCH] Add blocked permission check

---
 bin/check-home-permissions.py | 18 ++++++------
 bin/xymon-home.py             | 53 ++++++++++++++++++++++++++++++++---
 2 files changed, 58 insertions(+), 13 deletions(-)

diff --git a/bin/check-home-permissions.py b/bin/check-home-permissions.py
index 2d51a88..5083dcf 100755
--- a/bin/check-home-permissions.py
+++ b/bin/check-home-permissions.py
@@ -117,10 +117,10 @@ def check_homes(top):
             if users[home.name]['homeDirectory'][6:] != home.name:
                 bad_home_directory.append(': '.join([home.name, users[home.name]['homeDirectory']]))
             if users[home.name]['blocked'] == 'yes':
-                if home.st.st_mode != stat.S_IFDIR:
+                if home.st.st_mode & stat.S_IRWXU:
                     not_closed.append(home)
             else:
-                if home.st.st_mode != stat.S_IFDIR | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR:
+                if home.st.st_mode & stat.S_IRWXU != stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR:
                     not_open.append(home)
             del users[home.name]
         else:
@@ -193,6 +193,13 @@ if __name__ == '__main__':
     print('no nismap for home:   ' + str(len(no_nis_map)))
     print()
 
+    if no_blocked:
+        print('no blocked attr:')
+        print('----------------')
+        for home in no_blocked:
+            print(home)
+        print()
+
     if owner:
         print('bad owner or group:')
         print('-------------------')
@@ -223,13 +230,6 @@ if __name__ == '__main__':
             print(''.join([k, ': ', 'blocked=', v['blocked'], ' ', 'homeDirectory=', v['homeDirectory']]))
         print()
 
-    if no_blocked:
-        print('no blocked attr:')
-        print('----------------')
-        for home in no_blocked:
-            print(home)
-        print()
-
     if not_closed:
         print('home not closed:')
         print('----------------')
diff --git a/bin/xymon-home.py b/bin/xymon-home.py
index 4683742..7da56da 100755
--- a/bin/xymon-home.py
+++ b/bin/xymon-home.py
@@ -28,6 +28,9 @@ bad_home_directory = []
 no_ldap_user = []
 bad_nis_map = []
 no_nis_map = []
+no_blocked = []
+not_closed = []
+not_open = []
 
 
 class Home(object):
@@ -75,7 +78,14 @@ def search_ldap():
 
     ldap_users.search('*')
     for user in ldap_users:
-        users[user['uid'][0]] = user['homeDirectory'][0]
+        user_attrs = {}
+        user_attrs['homeDirectory'] = user['homeDirectory'][0]
+        if user['blocked']:
+            user_attrs['blocked'] = user['blocked'][0]
+        else:
+            no_blocked.append(user['uid'][0])
+            user_attrs['blocked'] = 'no'
+        users[user['uid'][0]] = user_attrs
 
     entries.search('cn: *, nisMapEntry: phd-home*', ['nisObject'], base=auto_home)
     for entry in entries:
@@ -109,8 +119,14 @@ def check_homes(top):
             acl.append(home)
 
         if home.name in users:
-            if users[home.name][6:] != home.name:
-                bad_home_directory.append(': '.join([home.name, users[home.name]]))
+            if users[home.name]['homeDirectory'][6:] != home.name:
+                bad_home_directory.append(': '.join([home.name, users[home.name]['homeDirectory']]))
+            if users[home.name]['blocked'] == 'yes':
+                if home.st.st_mode & stat.S_IRWXU:
+                    not_closed.append(home)
+            else:
+                if home.st.st_mode & stat.S_IRWXU != stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR:
+                    not_open.append(home)
             del users[home.name]
         else:
             no_ldap_user.append(home)
@@ -167,6 +183,9 @@ def run_check(xymon):
 
     content += 'home dirs:            ' + str(home_dirs) + '<br/>'
     content += 'strange ldap users:   ' + str(len(users)) + '<br/>'
+    content += 'no blocked attr:      ' + str(len(no_blocked)) + '<br/>'
+    content += 'home not closed:      ' + str(len(not_closed)) + '<br/>'
+    content += 'home not open:        ' + str(len(not_open)) + '<br/>'
     content += 'orphaned nis homes:   ' + str(len(nis_homes)) + '<br/>'
     content += 'orphaned nis shares:  ' + str(len(nis_shares)) + '<br/>'
     content += 'bad homeDirectory:    ' + str(len(bad_home_directory)) + '<br/>'
@@ -176,6 +195,16 @@ def run_check(xymon):
 
     xymon.section(title, content)
 
+    if no_blocked:
+        title = 'ldap user has no `blocked` attribute'
+        content = 'this is just an inconsistency and means the account is not blocked<br/><br/>'
+        if len(no_blocked) > 10:
+            content += 'user listing suppressed due to many entries (' + str(len(no_blocked)) + ')<br/>'
+        else:
+            content += ''.join([str(home), '<br/>'])
+        xymon.section(title, content)
+        xymon.color = pymon.STATUS_WARNING
+
     if owner:
         title = 'bad owner or group'
         content = 'home must be owned by the respective user and the group his user-private-group<br/><br/>'
@@ -192,6 +221,22 @@ def run_check(xymon):
         xymon.section(title, content)
         xymon.color = pymon.STATUS_CRITICAL
 
+    if not_closed:
+        title = 'home not closed (bad permissions)'
+        content = 'blocked user homes should have <code>u=---</code><br/><br/>'
+        for home in not_closed:
+            content += ''.join([str(home), '<br/>'])
+        xymon.section(title, content)
+        xymon.color = pymon.STATUS_CRITICAL
+
+    if not_open:
+        title = 'home not open (bad permissions)'
+        content = 'active user homes should have <code>u=rwx</code><br/><br/>'
+        for home in not_open:
+            content += ''.join([str(home), '<br/>'])
+        xymon.section(title, content)
+        xymon.color = pymon.STATUS_CRITICAL
+
     if acl:
         title = 'bad acls'
         content = 'home has posix.1e extended ACLs<br/>check acls using `getfacl`, which stands for `get fucking ACL`<br/><br/>'
@@ -206,7 +251,7 @@ def run_check(xymon):
         title = 'strange ldap users'
         content = 'these users seem to not have a home directory on the filesystem<br/><br/>'
         for k, v in users.items():
-            content += ': '.join([k, v]) + '<br/>'
+            content += ''.join([k, ': ', 'blocked=', v['blocked'], ' ', 'homeDirectory=', v['homeDirectory'], '<br/>'])
         xymon.section(title, content)
         xymon.color = pymon.STATUS_CRITICAL
 
-- 
GitLab