1""" 2Find number of ssh logins and authorised users (uses /var/log/auth.log) 3NOTE: This file is now deprecated in favour of the newer journald mechanism 4used in sshd-journald.py. This parser is still functional but is slower and 5has less features. Please switch over if possible. 6""" 7 8import re 9 10from logparse.formatting import* 11from logparse.util import readlog, resolve 12from logparse import config 13from logparse.load_parsers import Parser 14 15classSshd(Parser): 16 17def__init__(self): 18super().__init__() 19 self.name ="sshd" 20 self.info ="Find number of ssh logins and authorised users " 21"(uses /var/log/auth.log)" 22 self.deprecated =True 23 self.successor ="sshd_journald" 24 25defparse_log(self): 26 27 logger.warning("NOTE: This sshd parser is now deprecated. " 28"Please use sshd-journald if possible.") 29 logger.debug("Starting sshd section") 30 section =Section("ssh") 31 32 logger.debug("Searching for matches in{0}".format( 33 config.prefs.get("logs","auth"))) 34 authlog =readlog(config.prefs.get("logs","auth")) 35 matches = re.findall('.*sshd.*Accepted publickey for .* from .*', 36 authlog)# get all logins 37 invalid_matches = re.findall(".*sshd.*Invalid user .* from .*", authlog) 38 root_matches = re.findall("Disconnected from authenticating user root", 39 authlog) 40 logger.debug("Finished searching for logins") 41 42 users = []# list of users with format [username, number of logins] 43# for each item 44 data = [] 45 num =len(matches)# total number of logins 46 47for match in matches: 48 49# [('user', 'ip')] 50 entry = re.search('^.*publickey\sfor\s(\w*)\sfrom\s(\S*)', match) 51 52 user = entry.group(1) 53 ip = entry.group(2) 54 55 userhost = user +'@'+resolve(ip, 56 fqdn=config.prefs.get("sshd","sshd-resolve-domains")) 57 users.append(userhost) 58 59 logger.debug("Parsed list of authorised users") 60 61# Format authorised users 62 auth_data =Data(subtitle=plural('login', num) +' from', items=users) 63if(len(auth_data.items) ==1): 64# If only one user, do not display no of logins for this user 65 logger.debug("Found{0}logins for user{1}".format( 66 auth_data.orderbyfreq() 67 auth_data.truncl(config.prefs.getint("logparse","maxlist")) 68 logger.debug("Found{0}logins for{1}users".format( 69len(matches),len(users))) 70 section.append_data(auth_data) 71 72# Format invalid users 73 invalid_users = [] 74for match in invalid_matches: 75# [('user', 'ip')] 76 entry = re.search('^.*Invalid user (\S+) from (\S+).*', match) 77try: 78 user = entry.group(1) 79 ip = entry.group(2) 80except:# blank user field 81continue 82 83 userhost = user +'@'+ ip 84 invalid_users.append(userhost) 85 86 logger.debug("Parsed list of invalid users") 87 88 invalid_data =Data(subtitle=plural("attempted login", 89len(invalid_matches)) +" from " 90+plural("invalid user",len(invalid_users), print_quantity=False), 91 items=invalid_users) 92if(len(invalid_data.items) ==1): 93# If only one user, do not display no of logins for this user 94 logger.debug("Found{0}login attempts for user{1}" 95.format(len(invalid_matches), invalid_data.items[0])) 96 invalid_data.subtitle +=' '+ invalid_data.items[0] 97 invalid_data.orderbyfreq() 98 invalid_data.truncl(config.prefs.get("logparse","maxlist")) 99 logger.debug("Found{0}login attempts for invalid users" 100.format(len(invalid_matches))) 101 section.append_data(invalid_data) 102 103 logger.debug("Found{0}attempted logins for root". 104format(str(len(root_matches)))) 105 106 section.append_data(Data(subtitle=plural("attempted login", 107str(len(root_matches))) +" for root")) 108 109 logger.info("Finished sshd section") 110return section