#!/bin/bash
#
# test_security
#
# collect security settings
###############################################################
#
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
#
. `dirname $0`/uls_header
#
{ echo "D;$DT;${SETULSHOSTNAME:-$ULSHOSTNAME};Security;Settings;"
#
# /etc/sysconfig/security
#
if [[ -f /etc/sysconfig/security ]]; then
  W=`grep '^PERMISSION_SECURITY=' /etc/sysconfig/security | sed 's/.*PERMISSION_SECURITY="\?\([^ "]*\).*$/\1/'`
  [[ -n "$W" ]] && echo "V;;;;Settings;Security;'${W//\'/\\\'}'; "
fi
#
#
# /etc/sysconfig/kernel
#
if [[ -f /etc/sysconfig/kernel ]]; then
  W=`grep '^INITRD_MODULES=' /etc/sysconfig/kernel | sed 's/^INITRD_MODULES="*\([^"]*\)".*$/\1/'`
  echo "V;;;;;initrd - Module;'${W//\'/\\\'}'; "
fi
#
#
# CTRL-ALT-DEL
#
if [[ -f /etc/inittab ]]; then
  W=`grep '^ca:' /etc/inittab | cut -d ':' -f 4`
  echo "V;;;;;CTRL-ALT-DEL;'${W//\'/\\\'}'; "
fi
#
#
# GRUB Password
#
if [[ -f /boot/grub/menu.lst ]]; then
  W=`grep -q '^password' /boot/grub/menu.lst && echo 'X' || echo '-'`
  echo "V;;;;;Grub-PWD;'${W//\'/\\\'}'; "
fi
if [[ -f /boot/grub2/grub.cfg ]]; then
  W=`grep -q '^password' /boot/grub2/grub.cfg && echo 'X' || echo '-'`
  echo "V;;;;;Grub-PWD;'${W//\'/\\\'}'; "
fi
#
#
# rights of /var/log/messages
#
if [[ -f /var/log/messages ]]; then
  W=`ls -l /var/log/messages | cut -d ' ' -f 1`
  echo "V;;;;;Rights of messages;'${W//\'/\\\'}'; "
fi
#
# rights of /var/log/syslog
#
if [[ -f /var/log/syslog ]]; then
  W=`ls -l /var/log/syslog | cut -d ' ' -f 1`
  echo "V;;;;;Rights of syslog;'${W//\'/\\\'}'; "
fi
#
#
# Password - encryption
#
if [[ -f /etc/default/passwd ]]; then
  W=`grep '^CRYPT_FILES=' /etc/default/passwd | sed 's/CRYPT_FILES=//'`
  echo "V;;;;;Password-encryption;'${W//\'/\\\'}'; "
fi
#
#
# /etc/login.defs
#
if [[ -f /etc/login.defs ]]; then
  W=`egrep 'FTMP_FILE|UMASK' /etc/login.defs|grep -v "^#"|column -t`
  if [[ -n "$W" ]]; then
    echo "V;;;;;login.defs;'${W//\'/\\\'}'; "
  fi
fi
#
#
# xntp
#
if [[ -f /etc/ntp.conf ]]; then
  W=`grep '^server' /etc/ntp.conf|sed -s 's/^server //'`
  if [[ -n "$W" ]]; then
    echo "V;;;;;ntp;'${W//\'/\\\'}'; "
  fi
fi
#
#
# VmWare - Timesync
#
if [[ -x /usr/bin/vmware-toolbox-cmd ]]; then
  W=`/usr/bin/vmware-toolbox-cmd timesync status`
  if [[ -n "$W" ]]; then
    echo "V;;;;;VmWare Timesync;'${W//\'/\\\'}'; "
  fi
fi
#
#
# blocked user (pam_tally)
#
if which pam_tally >/dev/null 2>&1; then
  W=`pam_tally`
  if [[ -n "$W" ]]; then
    echo "V;;;;;pam_tally;'${W//\'/\\\'}'; "
  fi
fi
#
#
# /etc/ssh/sshd_config
#
W=`grep '^Protocol' /etc/ssh/sshd_config | awk '{print $2}'`
if [[ -z "$W" ]]; then
  echo "V;;;;;sshd-Protocol;2,1; "
else
  echo "V;;;;;sshd-Protocol;'${W//\'/\\\'}'; "
fi
W=`grep '^PermitRootLogin' /etc/ssh/sshd_config | awk '{print $2}'`
if [[ -z "$W" ]]; then
  echo "V;;;;;sshd-PermitRootLogin;yes; "
else
  echo "V;;;;;sshd-PermitRootLogin;'${W//\'/\\\'}'; "
fi
W=`grep '^X11Forwarding' /etc/ssh/sshd_config | awk '{print $2}'`
if [[ -z "$W" ]]; then
  echo "V;;;;;sshd-X11Forwarding;no; "
else
  echo "V;;;;;sshd-X11Forwarding;'${W//\'/\\\'}'; "
fi
W=`grep '^UsePrivilegeSeparation' /etc/ssh/sshd_config | awk '{print $2}'`
if [[ -z "$W" ]]; then
  echo "V;;;;;sshd-UsePrivilegeSeparation;yes; "
else
  echo "V;;;;;sshd-UsePrivilegeSeparation;'${W//\'/\\\'}'; "
fi
#
#
# Password length
#
if [[ -f /etc/security/pam_pwcheck.conf ]]; then
  W=`grep '^password:.*minlen=' /etc/security/pam_pwcheck.conf | sed 's/^password:.*minlen=\([0-9]*\)[^0-9].*/\1/'`
  if [[ -n "$W" ]]; then
    echo "V;;;;;Passwordlength;'${W//\'/\\\'}'; "
  fi
  W=`grep -v '^ *#' /etc/security/pam_pwcheck.conf`
  if [[ -n "$W" ]]; then
    echo "V;;;;Settings:Pam;pam_pwcheck.conf;'${W//\'/\\\'}';_"
  fi
fi
#
#
# User mit leerem Passwort
#
W=`awk -F ':' '$1 != "+" && $2 == "" {print $1}' /etc/shadow`
if [[ -n "$W" ]]; then
  echo "V;;;;Settings;User without password;'${W//\'/\\\'}'; ;adm"
fi
#
#
# Services
#
if which systemctl >/dev/null 2>&1; then
  W=`systemctl list-unit-files --type=service | awk '$2 == "enabled"{gsub("[.]service","");print $1}' | sort`
  if [[ -n "$W" ]]; then
    echo "V;;;;Settings:Services;systemd;'${W//\'/\\\'}';_;adm"
  fi
fi
if which chkconfig >/dev/null 2>&1; then
  W=`chkconfig 2>/dev/null | awk '$2 != "off"{print $1}' | sort`
  if [[ -n "$W" ]]; then
    echo "V;;;;Settings:Services;chkconfig;'${W//\'/\\\'}';_;adm"
  fi
  #
  # chkconfig - xinetd
  W=`chkconfig --list 2>/dev/null | awk '/inetd based services/ {inet = 1};$2 != "off" && inet == 1 {print $1}' | sort`
  if [[ -n "$W" ]]; then
    echo "V;;;;Settings:Services;xinetd;'${W//\'/\\\'}';_;adm"
  fi
fi
#
#
# getent passwd / group
#
if egrep -q '^[[:blank:]]*(passwd|group):[[:blank:]]+.*winbind' /etc/nsswitch.conf || egrep -q '^[[:blank:]]*account[[:blank:]]+include[[:blank:]].*winbind' /etc/pam.d/common-account; then
  send_test_value -s adm Security "Settings:getent" "passwd" $DT "$(sort /etc/passwd)" '_'
  send_test_value -s adm Security "Settings:getent" "group" $DT "$(sort /etc/group)" '_'
else
  W=`getent passwd | sort`
  if [[ ${#W} -gt 20000 ]]; then
    getent passwd | sort | send_stdin_file -s adm Security "Settings:getent" "passwd" $DT "passwd.txt"
  elif [[ -n "$W" ]]; then
    echo "V;;;;Settings:getent;passwd;'${W//\'/\\\'}';_;adm"
  fi
  #
  W=`getent group | sort`
  if [[ ${#W} -gt 20000 ]]; then
    getent group | sort | send_stdin_file -s adm Security "Settings:getent" "group" $DT "group.txt"
  elif [[ -n "$W" ]]; then
    echo "V;;;;Settings:getent;group;'${W//\'/\\\'}';_;adm"
  fi
fi
#
#
# /etc/security/access.conf
#
if [[ -f /etc/security/access.conf ]]; then
  W=`grep -v '^ *#' /etc/security/access.conf`
  if [[ -n "$W" ]]; then
    echo "V;;;;Settings:Pam;access.conf;'${W//\'/\\\'}';_;adm"
  fi
fi
#
#
# Mount-Optionen
#
W=`awk '$1 !~ "#" && $2 ~ "/tmp|/var|/home" {print $2, $4}' /etc/fstab`
if [[ -n "$W" ]]; then
  echo "V;;;;Settings:Mount;fstab;'${W//\'/\\\'}';_;adm"
fi
#
#
# Postfix
#
if [[ -d /etc/postfix ]]; then
  W=`egrep '^ *relayhost|^ *disable_dns_lookups|^ *myhostname' /etc/postfix/main.cf`
  if [[ -n "$W" ]]; then
    echo "V;;;;Settings:Postfix;main.cf;'${W//\'/\\\'}';_;adm"
  fi
  if [[ -f /etc/postfix/canonical ]]; then
    W=`grep -v '^ *#' /etc/postfix/canonical`
    if [[ -n "$W" ]]; then
      echo "V;;;;Settings:Postfix;canonical;'${W//\'/\\\'}';_;adm"
    fi
  fi
  if [[ -f /etc/postfix/sender_canonical ]]; then
    W=`grep -v '^ *#' /etc/postfix/sender_canonical`
    if [[ -n "$W" ]]; then
      echo "V;;;;Settings:Postfix;sender_canonical;'${W//\'/\\\'}';_;adm"
    fi
  fi
  W=`awk '/^ *root:/ {print $2}' /etc/aliases`
  if [[ -n "$W" ]]; then
    echo "V;;;;Settings:Postfix;root-alias;'${W//\'/\\\'}';_;adm"
  fi
  if [[ -f /etc/postfix/transport ]]; then
    W=`grep -v '^ *#' /etc/postfix/transport`
    if [[ -n "$W" ]]; then
      echo "V;;;;Settings:Postfix;transport;'${W//\'/\\\'}';_;adm"
    fi
  fi
fi
#
#
# LDAP
#
if [[ -f /etc/ldap.conf && "`awk '/^base/ && ! /dc=example,dc=com/ {print $2}' /etc/ldap.conf`" != "" ]]; then
  W="`egrep -i '^ *uri|^ *base|^ *nss_base_' /etc/ldap.conf`"
  if [[ -n "$W" ]]; then
    echo "V;;;;Settings:Ldap;summary;'${W//\'/\\\'}';_;adm"
  fi
fi
#
#
# Kerberos
#
if [[ -f /etc/krb5.conf && "`awk '$1 == "default_realm" && $2 == "=" && $3 !~ "EXAMPLE" { print $3 }' /etc/krb5.conf`" != "" ]]; then
  W="`sed 's/^[[:blank:]]*//g' /etc/krb5.conf | egrep '^default_realm|^kdc'`"
  if [[ -n "$W" ]]; then
    echo "V;;;;Settings:Kerberos;summary;'${W//\'/\\\'}';_;adm"
  fi
fi
#
#
# ss / netstat
#
if which ss &>/dev/null; then
  W=$(ss -ntlp | awk '/LISTEN/{n=split($4,a,":");l=a[n];split($NF,a,"\"");printf("%s %-18s %s\n", l, $4, a[2])}' | sort -n | cut -d ' ' -f 2-)
  if [[ -n "$W" ]]; then
    echo "V;;;;Settings:Services;Listen;'${W//\'/\\\'}';_;adm"
  fi
elif which netstat &>/dev/null; then
  W=$(netstat -ntpl | awk '/LISTEN/{printf("%-18s %s\n", $4, $7)}' | sort -t : -g -k 2,2 -k 4,4)
  if [[ -n "$W" ]]; then
    echo "V;;;;Settings:Services;Listen;'${W//\'/\\\'}';_;adm"
  fi
fi
#
#
# /etc/security/pam_unix2.conf
#
if [[ -f /etc/security/pam_unix2.conf ]]; then
  W=`grep -v '^ *#' /etc/security/pam_unix2.conf`
  if [[ -n "$W" ]]; then
    echo "V;;;;Settings:Pam;pam_unix2;'${W//\'/\\\'}';_;adm"
  fi
fi
#
#
#
# /etc/pam.d/common-auth
#
W=`grep -v '^ *#' /etc/pam.d/common-auth`
if [[ -n "$W" ]]; then
  echo "V;;;;Settings:Pam;common-auth;'${W//\'/\\\'}';_;adm"
fi
#
#
# /etc/pam.d/common-password
#
W=`grep -v '^ *#' /etc/pam.d/common-password`
if [[ -n "$W" ]]; then
  echo "V;;;;Settings:Pam;common-password;'${W//\'/\\\'}';_;adm"
fi
#
#
# /etc/pam.d/common-account
#
W=`grep -v '^ *#' /etc/pam.d/common-account`
if [[ -n "$W" ]]; then
  echo "V;;;;Settings:Pam;common-account;'${W//\'/\\\'}';_;adm"
fi
#
#
# Firewall
#
if iptables -nL | egrep -q "DROP|REJECT"; then
  echo "V;;;;Settings;Firewall;on; ;all"
  iptables -vnL | awk -v listen="$(ss -ltn | sed -n 's/.*:\([1-9][0-9]*\)[^0-9].*/\1/p' | sort -nu)" 'BEGIN {
  n = split(listen, a)
  for( i = 1; i <= n; i++ )
    lsn[a[i]] = 1
  while( 0 < getline <"/proc/net/dev" )
  { if( $1 != "lo:" && $2 ~ /[0-9]/ )
    { gsub(":", "", $1)
      iface[$1] = 1
    }
  }
  close("/proc/net/dev")
}

#
# chains[<chain>] = 1

$1 == "Chain" {
  c = $2
  if( $3 !~ /ACCEPT|LOG|DROP|TCPMSS|REJECT/ )
    chains[$2] = 1
}

#
# lu[<inputchain>:<source>] = <target>
# lp[<inputchain>:<target>:<source>:<tcp|udp|multiport>] = <ports>

$1 ~ /[0-9]+/ && $2 ~ /[0-9]+/ && c !~ /FORWARD|OUTPUT/ {
  if( $4 ~ /all|tcp|udp/ && $3 != "DROP" )
  { if( $10 == "" )
    { if( lu[c":"$6] )
        lu[c":"$6] = lu[c":"$6] " " $3
      else
        lu[c":"$6] = $3
    }
    else if( $10 ~ /tcp|udp/ && $11 ~ /dpt/ )
    { gsub("dpts?:", "", $11)
      if( lp[c":"$3":"$6":"$10] )
        lp[c":"$3":"$6":"$10] = lp[c":"$3":"$6":"$10] ", " $11
      else
        lp[c":"$3":"$6":"$10] = $11
    }
    else if( $10 == "multiport" && $11 == "dports" )
    { if( $4 ~ /tcp|udp/ )
        tu = $4
      else
        tu = $10
      if( lp[c":"$3":"$6":"tu] )
        lp[c":"$3":"$6":"tu] = lp[c":"$3":"$6":"tu] ", " $12
      else
        lp[c":"$3":"$6":"tu] = $12
    }
  }
}

END {
  printf("V;;;;Settings:Firewall;services;\"")
  for( f in iface )
  { if( lu["INPUT:"f] == "ACCEPT" )
      print f " all"
    else if( lu["INPUT:"f] ~ /DROP|REJECT/ )
      print f " nothing"
    else
    { n = split(lu["INPUT:"f], a)
      if( n )
      { for( i = 1; i <= n; i++ )
        { if( lp[a[i]":ACCEPT:*:tcp"] || lp[a[i]":ACCEPT:"f":tcp"] )
          { print f " tcp: " lp[a[i]":ACCEPT:*:tcp"] " " lp[a[i]":ACCEPT:"f":tcp"]
            m = split(lp[a[i]":ACCEPT:*:tcp"], b, ", ")
            for( j = 1; j <= m; j++ )
            { if( split(b[j], bb, ":") == 2 )
              { for( k = bb[1]; k <= bb[2]; k++ )
                  delete lsn[k]
              }
              else
                delete lsn[b[j]]
            }
            m = split(lp[a[i]":ACCEPT:"f":tcp"], b, ", ")
            for( j = 1; j <= m; j++ )
            { if( split(b[j], bb, ":") == 2 )
              { for( k = bb[1]; k <= bb[2]; k++ )
                  delete lsn[k]
              }
              else
                delete lsn[b[j]]
            }
          }
          if( lp[a[i]":ACCEPT:*:udp"] || lp[a[i]":ACCEPT:"f":udp"] )
            print f " udp: " lp[a[i]":ACCEPT:*:udp"] " " lp[a[i]":ACCEPT:"f":udp"]
          if( lp[a[i]":ACCEPT:*:multiport"] || lp[a[i]":ACCEPT:"f":multiport"] )
            print f " multiport: " lp[a[i]":ACCEPT:*:multiport"] " " lp[a[i]":ACCEPT:"f":multiport"]
        }
      }
      else
      { if( lp["INPUT:ACCEPT:*:tcp"] || lp["INPUT:ACCEPT:"f":tcp"] )
        { print f " tcp: " lp["INPUT:ACCEPT:*:tcp"] " " lp["INPUT:ACCEPT:"f":tcp"]
          m = split(lp["INPUT:ACCEPT:*:tcp"], b, ", ")
          for( j = 1; j <= m; j++ )
          { if( split(b[j], bb, ":") == 2 )
            { for( k = bb[1]; k <= bb[2]; k++ )
                delete lsn[k]
            }
            else
              delete lsn[b[j]]
          }
          m = split(lp["INPUT:ACCEPT:"f":tcp"], b, ", ")
          for( j = 1; j <= m; j++ )
          { if( split(b[j], bb, ":") == 2 )
            { for( k = bb[1]; k <= bb[2]; k++ )
                delete lsn[k]
            }
            else
              delete lsn[b[j]]
          }
        }
        if( lp["INPUT:ACCEPT:*:udp"] || lp["INPUT:ACCEPT:"f":udp"] )
          print f " udp: " lp["INPUT:ACCEPT:*:udp"] " " lp["INPUT:ACCEPT:"f":udp"]
        if( lp["INPUT:ACCEPT:*:multiport"] || lp["INPUT:ACCEPT:"f":multiport"] )
          print f " multiport: " lp["INPUT:ACCEPT:*:multiport"] " " lp["INPUT:ACCEPT:"f":multiport"]
      }
    }
  }
  if( lu["INPUT:*"] == "ACCEPT" )
    print "* all"
  else if( lu["INPUT:*"] ~ /DROP|REJECT/ )
    print "* nothing"
  else
  { n = split(lu["INPUT:*"], a)
    if( n )
    { for( i = 1; i <= n; i++ )
      { if( lp[a[i]":ACCEPT:*:tcp"] )
        { print "* tcp: " lp[a[i]":ACCEPT:*:tcp"]
          m = split(lp[a[i]":ACCEPT:*:tcp"], b, ", ")
          for( j = 1; j <= m; j++ )
          { if( split(b[j], bb, ":") == 2 )
            { for( k = bb[1]; k <= bb[2]; k++ )
                delete lsn[k]
            }
            else
              delete lsn[b[j]]
          }
        }
        if( lp[a[i]":ACCEPT:*:udp"] )
          print "* udp: " lp[a[i]":ACCEPT:*:udp"]
        if( lp[a[i]":ACCEPT:*:multiport"] )
          print "* multiport: " lp[a[i]":ACCEPT:*:multiport"]
      }
    }
    else
    { if( lp["INPUT:ACCEPT:*:tcp"] )
      { print "* tcp: " lp["INPUT:ACCEPT:*:tcp"]
        m = split(lp["INPUT:ACCEPT:*:tcp"], b, ", ")
        for( j = 1; j <= m; j++ )
        { if( split(b[j], bb, ":") == 2 )
          { for( k = bb[1]; k <= bb[2]; k++ )
              delete lsn[k]
          }
          else
            delete lsn[b[j]]
        }
      }
      if( lp["INPUT:ACCEPT:*:udp"] || lp["INPUT:ACCEPT:"f":udp"] )
        print "* udp: " lp["INPUT:ACCEPT:*:udp"]
      if( lp["INPUT:ACCEPT:*:multiport"] )
        print "* multiport: " lp["INPUT:ACCEPT:*:multiport"]
    }
  }
  print "\";_;adm"
  cp = ""
  for( p in lsn )
    cp = cp (cp ? ", " : "") p
  if( cp )
    print "V;;;;Settings:Firewall;blocked services;" cp; "_;adm"
}'
else
  echo "V;;;;Settings;Firewall;off; ;all"
fi
} | send_test_tab
