# HG changeset patch
# User Jean-Francois Pieronne <jf.pieronne@laposte.net>
# Date 1587571483 -7200
#      Wed Apr 22 18:04:43 2020 +0200
# Node ID 293b91237c6350e12bc898eae60cb74227ff7fab
# Parent  688474a7cdacb9cbd7048767c859b20b7dbfe230
secrules/rules11.py initial version

diff --git a/secrules/rules11.py b/secrules/rules11.py
new file mode 100644
--- /dev/null
+++ b/secrules/rules11.py
@@ -0,0 +1,395 @@
+# -*- coding: iso-8859-1 -*-
+__version__ = '1.0'
+
+from common import level_rule
+import os
+from vms import starlet
+from vms.rtl import lib
+from vms import user
+from vms import ossdef, uaidef, syidef, prvdef
+from vms import itemList
+from FindFile import FindFile
+from FindFile import file_exists
+from getMailObjectInfo import getMailObjectInfo
+
+@level_rule(2)
+def rule1101(fo, fmt):
+    """ Many, or all, of their mail files may reside on a different system.  
+This prevents analysis of the mail files associated with these users."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1101'
+        print>>fo, '========='
+
+    with os.popen('@MAIL_FORWARD.COM') as p:
+        r = [x[1:-1] for x in p]
+    for e in r:
+        if not (e == ''):
+            if fmt:
+                print>>fo, '1101�2�', e
+            else:
+                print>>fo, e
+
+@level_rule(2)
+def rule1102(fo, fmt):
+    """ A users mail file should limit access to the SYSTEM and OWNER 
+(typically RW for SYSTEM and OWNER and no access for GROUP and WORLD).  
+The listed files should have their protection changed to (RW,RW,,)."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1102'
+        print>>fo, '========='
+
+    all_users = user.all_users()
+
+    it = [itemList.itemList (code = ossdef.OSS__PROTECTION, dtype = itemList.il_unsignedWord),]
+    for u in all_users.values():
+        df = u.defdev + u.defdir + 'MAIL.MAI'
+        if file_exists(df):
+            prot = starlet.get_security(objnam=df, clsnam='FILE',itmlst=it)[1][ossdef.OSS__PROTECTION]
+            if (prot != 0xFFCC):
+                if fmt:
+                    print>>fo, '1102�2�', df
+                else:
+                    print>>fo, df
+                    print>>fo, ' ' * 10, lib.format_sogw_prot (prot)[1]
+
+@level_rule(2)
+def rule1103(fo, fmt):
+    """ A users mail file should only be owned by that user.  The owner of a 
+file has full access to the file including read, write and delete privileges 
+on that file.  These files should be changed to specify the proper owner."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1103'
+        print>>fo, '========='
+
+    all_users = user.all_users()
+    
+    it = [itemList.itemList (code = ossdef.OSS__OWNER, dtype = itemList.il_unsignedLong),]
+    for u in all_users.values():
+        df = u.defdev+ u.defdir+'MAIL.MAI'
+        if file_exists(df):
+            own = starlet.get_security (objnam=df, clsnam='FILE',itmlst=it)[1][ossdef.OSS__OWNER]
+            g = int(own / 65536)
+            m = int(own - (g *65536))
+            if (u.uic_group != g) or (u.uic_member != m):
+                if fmt:
+                    print>>fo, '1103�2�', u.username
+                else:
+                    print>>fo, "%s [%o,%o] %s [%o,%o]" % (df, g, m, u.username, u.uic_group, u.uic_member) 
+
+@level_rule(3)
+def rule1104(fo, fmt):
+    """ During review of the system MAIL object, either 1) The attempt to 
+gather information on the systems MAIL object was unsuccessful.  This implies 
+that there is no MAIL object available on the system, thus prohibiting the 
+use of VMS MAIL.  -OR- 2) The information collected on the system MAIL object 
+is incomplete.  This implies that the object is not correctly configured or 
+that the last system upgrade (for openVMS) may have been incomplete."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1104'
+        print>>fo, '========='
+
+    p, a, u = getMailObjectInfo()
+
+    if p:
+        if fmt:
+            print>>fo, '1104�3� MAIL object present'
+        else:
+            print>>fo, 'MAIL object present'
+
+@level_rule(4)
+def rule1105(fo, fmt):
+    """ This prohibits mail transmissions across the network."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1105'
+        print>>fo, '========='
+
+    p, a, u = getMailObjectInfo()
+
+    if not a:
+        if fmt:
+            print>>fo, '1105�4� Account MAIL$SERVER missing'
+        else:
+            print>>fo, 'Account MAIL$SERVER missing'
+
+@level_rule(2)
+def rule1106(fo, fmt):
+    """ Not having this flag set allows the account unrestricted access, 
+which is both unnecessary and undesirable.  The RESTRICTED flag should 
+be set on this account."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1106'
+        print>>fo, '========='
+
+    p, a, u = getMailObjectInfo()
+    if a and not (u.flags & uaidef.UAI_M_RESTRICTED):
+        if fmt:
+            print>>fo, '1106�2� Account MAIL$SERVER not RESTRICTED'
+        else:
+            print>>fo, 'Account MAIL$SERVER not RESTRICTED'
+
+@level_rule(2)
+def rule1107(fo, fmt):
+    """ This can permit someone to exploit the privileges of this account, 
+and presents a risk to the systems overall security.  This account should 
+have its UIC changed to a non-privileged value, i.e.  one whose group number 
+is greater than that specified in the SYSGEN parameter MAXSYSGROUP."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1107'
+        print>>fo, '========='
+
+    p, a, u = getMailObjectInfo()
+    if  not a: return
+
+    if (u.uic_group <= lib.getsyi(syidef.SYI__MAXSYSGROUP)[1]):
+        if fmt:
+            print>>fo, '1107�2� Account MAIL$SERVER have System Group'
+        else:
+            print>>fo, "%s [%o,%o]" % ('Account MAIL$SERVER System Group', u.uic_group, u.uic_member)
+
+@level_rule(4)
+def rule1108(fo, fmt):
+    """ This effectively disables this account for any use.  This condition 
+inhibits mail transmission across the network."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1108'
+        print>>fo, '========='
+
+    p, a, u = getMailObjectInfo()
+    if not a: return
+
+    if (u.flags & uaidef.UAI_M_DISACNT):
+        if fmt:
+            print>>fo, '1108�4� Account MAIL$SERVER is DISUSER'
+        else:
+            print>>fo, 'Account MAIL$SERVER is DISUSER'
+
+@level_rule(1)
+def rule1109(fo, fmt):
+    """ This account should be assigned a password.  Not having a password on 
+this account may grant access to the system via this account from outside 
+processes, which could exploit this vulnerability."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1109'
+        print>>fo, '========='
+
+    p, a, u = getMailObjectInfo()
+    if not a: return
+
+    if (u.pwd_length < 8):
+        if fmt:
+            print>>fo, '1109�1� Account MAIL$SERVER Password Length'
+        else:
+            print>>fo, 'Account MAIL$SERVER Password Length', u.pwd_length 
+
+@level_rule(4)
+def rule1110(fo, fmt):
+    """ This prohibits mail transmissions across the network."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1110'
+        print>>fo, '========='
+
+    p, a, u = getMailObjectInfo()
+    if not a: return
+
+    if ((u.network_access_p != '\x00\x00\x00') and 
+        (u.network_access_s != '\x00\x00\x00')):
+        if fmt:
+            print>>fo, '1110�4� MAIL$SERVER no Netwrok Access'
+        else:
+            print>>fo, 'Account MAIL$SERVER no Netwrok Access'
+
+@level_rule(2)
+def rule1111(fo, fmt):
+    """ The mail object account has 1) BATCH, 2) REMOTE, 3) DIALUP, and/or 4) 
+LOCAL access enabled.  This permits respective logins to the system:  1) from 
+batch jobs submitted by other users which can specify this account as the 
+user; 2) by a user from a remote node; 3) utilizing a modem; 4) by a local 
+user.  This account should have these accesses disabled."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1111'
+        print>>fo, '========='
+
+    p, a, u = getMailObjectInfo()
+    if not a: return
+
+    if ((u.batch_access_p != '\xff\xff\xff') and
+        (u.batch_access_s != '\xff\xff\xff')):
+            if fmt:
+                print>>fo, '1111�2� MAIL$SERVER have REMOTE Access'
+            else:
+                print>>fo, 'Account MAIL$SERVER have REMOTE Access'
+
+    if ((u.remote_access_p != '\xff\xff\xff') and
+        (u.remote_access_s != '\xff\xff\xff')):
+            if fmt:
+                print>>fo, '1111�2� MAIL$SERVER have REMOTE Access'
+            else:
+                print>>fo, 'Account MAIL$SERVER have REMOTE Access'
+
+    if ((u.dialup_access_p != '\xff\xff\xff') and 
+        (u.dialup_access_s != '\xff\xff\xff')):
+            if fmt:
+                print>>fo, '1111�2� MAIL$SERVER have DIALUP Access'
+            else:
+                print>>fo, 'Account MAIL$SERVER have DIALUP Access'
+
+@level_rule(4)
+def rule1112(fo, fmt):
+    """ This account requires TMPMBX and NETMBX privileges in order to 
+function.  Lack of these privileges can impede mail transmissions."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1112'
+        print>>fo, '========='
+
+    p, a, u = getMailObjectInfo()
+    if not a: return
+
+    if not (u.priv & prvdef.PRV_M_NETMBX):
+        if fmt:
+            print>>fo, '1112�4� Account MAIL$SERVER privilege NETMBX missing'
+        else:
+            print>>fo, 'Account MAIL$SERVER privilege NETMBX missing'
+    if not (u.def_priv & prvdef.PRV_M_NETMBX):
+        if fmt:
+            print>>fo, '1112�4� Account MAIL$SERVER default privilege NETMBX missing'
+        else:
+            print>>fo, 'Account MAIL$SERVER default privilege NETMBX missing'
+
+    if not (u.priv & prvdef.PRV_M_TMPMBX):
+        if fmt:
+            print>>fo, '1112�4� Account MAIL$SERVER privilege TMPMBX missing'
+        else:
+            print>>fo, 'Account MAIL$SERVER privilege TMPMBX missing'
+    if not (u.def_priv & prvdef.PRV_M_TMPMBX):
+        if fmt:
+            print>>fo, '1112�4� Account MAIL$SERVER default privilege TMPMBX missing'
+        else:
+            print>>fo, 'Account MAIL$SERVER default privilege TMPMBX missing'
+
+@level_rule(2)
+def rule1113(fo, fmt):
+    """ If the account contains other weaknesses (such as an ability to access 
+the system and its resources via this account) then these extra privileges may 
+allow malicious use of this account to gain unauthorized access to system 
+objects. This account requires only TMPMBX and NETMBX privileges to function 
+properly."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1113'
+        print>>fo, '========='
+
+    p, a, u = getMailObjectInfo()
+    if not a: return
+
+    msk_prv = prvdef.PRV_M_NETMBX | prvdef.PRV_M_TMPMBX
+    if (u.def_priv ^msk_prv) != 0:
+        if fmt:
+            print>>fo, '1113�2� Account MAIL$SERVER excessive default privileges' 
+        else:
+            print>>fo, 'Account MAIL$SERVER excessive default privileges' 
+    if (u.priv ^msk_prv) != 0:
+        if fmt:
+            print>>fo, '1113�2� Account MAIL$SERVER excessive privileges'
+        else:
+            print>>fo, 'Account MAIL$SERVER excessive privileges'
+
+@level_rule(2)
+def rule1114(fo, fmt):
+    """ This may allow this file to be corrupted or deleted by an 
+unauthorized user."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1114'
+        print>>fo, '========='
+
+    it = [itemList.itemList (code = ossdef.OSS__OWNER, dtype = itemList.il_unsignedLong),]
+         
+    own = starlet.get_security (objnam='SYS$SYSTEM:VMSMAIL_PROFILE.DATA', clsnam='FILE',itmlst=it)[1][ossdef.OSS__OWNER]
+    g = int(own / 65536)
+    m = int(own - (g *65536))
+    if (g != 1) or (m != 4):
+        if fmt:
+            print>>fo, '1114�2� SYS$SYSTEM:VMSMAIL_PROFILE.DATA bad owner'
+        else:
+            print>>fo, "%s [%o,%o]" % ('SYS$SYSTEM:VMSMAIL_PROFILE.DATA bad owner', g, m,)
+    
+@level_rule(2)
+def rule1115(fo, fmt):
+    """ This may allow this file to be corrupted or deleted by unauthorized 
+users."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1115'
+        print>>fo, '========='
+
+    it = [ itemList.itemList (code = ossdef.OSS__PROTECTION, dtype = itemList.il_unsignedWord)]
+    prot = starlet.get_security (objnam='SYS$SYSTEM:VMSMAIL_PROFILE.DATA', clsnam='FILE',itmlst=it)[1][ossdef.OSS__PROTECTION]
+
+    if (prot != 0xFF88):
+        if fmt:
+            print>>fo, '1115�2� SYS$SYSTEM:VMSMAIL_PROFILE.DATA bad protection'
+        else:
+            print>>fo, 'SYS$SYSTEM:VMSMAIL_PROFILE.DATA', lib.format_sogw_prot (prot)[1]
+    
+@level_rule(2)
+def rule1116(fo, fmt):
+    """ This will prevent the mail system from functioning.  It also may 
+indicate tampering with the operational environment."""
+
+    if not fmt:
+        print>>fo
+        print>>fo, 'RULE 1116'
+        print>>fo, '========='
+
+    if not file_exists('SYS$SYSTEM:MAIL_SERVER.EXE'):
+        if fmt:
+            print >>fo, '1116�2�SYS$SYSTEM:MAIL_SERVER.EXE not exists'
+        else:
+            print >>fo, 'SYS$SYSTEM:MAIL_SERVER.EXE not exists'
+
+if __name__ == '__main__':
+    import sys
+    fo = open(sys.argv[1], 'w') if len(sys.argv) > 1 else sys.stdout
+    rule1101(fo, len(sys.argv) > 2)
+    rule1102(fo, len(sys.argv) > 2)
+    rule1103(fo, len(sys.argv) > 2)
+    rule1104(fo, len(sys.argv) > 2)
+    rule1105(fo, len(sys.argv) > 2)
+    rule1106(fo, len(sys.argv) > 2)
+    rule1107(fo, len(sys.argv) > 2)
+    rule1108(fo, len(sys.argv) > 2)
+    rule1109(fo, len(sys.argv) > 2)
+    rule1110(fo, len(sys.argv) > 2)
+    rule1111(fo, len(sys.argv) > 2)
+    rule1112(fo, len(sys.argv) > 2)
+    rule1113(fo, len(sys.argv) > 2)
+    rule1114(fo, len(sys.argv) > 2)
+    rule1115(fo, len(sys.argv) > 2)
+    rule1116(fo, len(sys.argv) > 2)