diff --git a/parsing.py b/parsing.py index ce2f181..8f53ef2 100644 --- a/parsing.py +++ b/parsing.py @@ -1,5 +1,5 @@ # Cisco config parsing -# Create 2 dictionaries with global and interface options +# Creates 2 dictionaries with global and interface options # # Global dictionary # {'ip': {'dhcp_snooping': {...}, 'arp_inspection': {...}, 'ssh': {...}, 'active_service': [...], 'http': {...}}, @@ -25,244 +25,34 @@ parse_iface = Suppress('interface ') + restOfLine iface_global = {} -parse_enable_password = Suppress('enable') + MatchFirst(['secret', 'password']) + Optional( - Word(nums) + Suppress(White(exact=1))) + Suppress(restOfLine) -parse_active_service = Suppress('service ') + restOfLine -parse_disable_service = Suppress('no service ') + restOfLine -parse_version = Suppress('version ') + restOfLine -parse_ipv6 = Suppress('ipv6 ') + restOfLine -parse_ipv6_sourceguard = Suppress('source-guard ') + restOfLine -parse_ipv6_snooping = Suppress('snooping ') + restOfLine -parse_ipv6_raguard = Suppress('nd raguard ') + restOfLine -parse_ipv6_destinationguard = Suppress('destination-guard ') + restOfLine -parse_ipv6_dhcpguard = Suppress('dhcp guard ') + restOfLine -parse_lldp = Suppress('lldp ') + restOfLine -parse_model = Suppress('boot system flash bootflash:') + restOfLine -parse_username = Suppress('username ') + restOfLine -parse_aaa = Suppress('aaa ') + restOfLine -parse_stp = Suppress('spanning-tree ') + restOfLine -parse_line = Suppress('line ') + restOfLine -parse_ip_ssh = Suppress('ip ssh ') + restOfLine -parse_vstack = Suppress('no') + 'vstack' -parse_ip_dhcp = NotAny(White()) + Suppress('ip dhcp snooping') + Optional( - Suppress('vlan') + Word(nums) + ZeroOrMore(Suppress(',') + Word(nums))) -parse_ip_arp = NotAny(White()) + Suppress('ip arp inspection') + Suppress('vlan') + Word(nums) + ZeroOrMore( - Suppress(',') + Word(nums)) -parse_ip_service = NotAny(White()) + Suppress('ip') + MatchFirst(['finger', 'identd', 'source-route', 'bootp server']) -parse_ip_http = NotAny(White()) + Suppress('ip http ') + restOfLine -authentication = Suppress('authentication ') + restOfLine -authorization = Suppress('authorization ') + restOfLine -accounting = Suppress('accounting ') + restOfLine -parse_vtp = Suppress('vtp ') + restOfLine - - -# Parse any attributes with whitespace as first symbol into list -# Input: line with futher options (starts with whitespaces) -# Sample: interface Loopback1 -# Output: further options list, next line (otherwise program may skip next line due to cursor placement) -# Sample: ['description -= MGMT - core.nnn048.nnn =-', 'ip address 172.21.24.140 255.255.255.255'], '!' -def get_attributes(config): - options_list = [] - option = White(exact=1) + Suppress(Optional(White())) + restOfLine - next_line = config.readline() - try: - option_parse = option.parseString(next_line) - while option_parse[0] == ' ': - options_list.append(option_parse[-1]) - next_line = config.readline() - option_parse = option.parseString(next_line) - except: - pass - return options_list, next_line - - -# Parse username options -# Input: line with user options -# Sample: vasya privilege 15 secret 5 $1$0k5Q$3h/ZPjj8T0iHu9DL/Ejt30 -# Output: user's options dictionary -# Sample: {'vasya': {'password_type': '5', 'privilege': '15'}} -def _globalParse___username_attributes(line): - username_dict = {} - username = (Word(printables))('user') - privilege = (Suppress('privilege') + Word(nums))('priv_num') - password_type = (Suppress(MatchFirst(['secret', 'password'])) + Word(nums))('pass_type') - parse_username = (username + Optional(privilege) + password_type + Suppress(restOfLine)) - result = parse_username.parseString(line) - - username_dict[result.user] = {} - username_dict[result.user]['password_type'] = result.pass_type.asList()[0] - try: - username_dict[result.user]['privilege'] = result.priv_num.asList()[0] - except AttributeError: - pass - return username_dict - - -# Parse AAA options -# Input: line with AAA options, type of AAA, login count -# Sample: login default group radius local, authentication, 1 -# Output: AAA option dictionary -# Sample: {'login1': {'list': 'default', 'methods': ['radius', 'local']}} -def _globalParse___aaa_attributes(line, type, count_aaa): - aaa_dict = {} - - parse_authentication_options = Suppress('login') + Word(printables) + OneOrMore(Optional(Suppress('group')) - + Word(printables)) - parse_authorization_options = MatchFirst(['exec', 'login']) + Word(printables) + OneOrMore( - Optional(Suppress('group')) - + Word(printables)) - parse_accounting_options = MatchFirst(['exec', 'network']) + Word(printables) + \ - MatchFirst(['start-stop', 'stop-only', 'stop']) + OneOrMore(Optional(Suppress('group')) + - Word(printables)) - - if type == 'authentication': - result = parse_authentication_options.parseString(line) - aaa_dict.update({'login' + str(count_aaa): {}}) - aaa_dict['login' + str(count_aaa)]['list'] = result.pop(0) - aaa_dict['login' + str(count_aaa)]['methods'] = result.asList() - elif type == 'authorization': - result = parse_authorization_options.parseString(line) - aaa_dict.update({'login' + str(count_aaa): {}}) - aaa_dict['login' + str(count_aaa)]['login'] = result.pop(0) - aaa_dict['login' + str(count_aaa)]['list'] = result.pop(0) - aaa_dict['login' + str(count_aaa)]['methods'] = result.asList() - elif type == 'accounting': - result = parse_accounting_options.parseString(line) - aaa_dict.update({'login' + str(count_aaa): {}}) - aaa_dict['login' + str(count_aaa)]['login'] = result.pop(0) - aaa_dict['login' + str(count_aaa)]['list'] = result.pop(0) - aaa_dict['login' + str(count_aaa)]['record'] = result.pop(0) - aaa_dict['login' + str(count_aaa)]['methods'] = result.asList() - - return aaa_dict - - - - - -# Parse SSH options -# Input: line with ssh option -# Sample: ip ssh time-out 30 -# Output: ssh option dictionary -# Sample: {'time-out': '30'} -def _globalParse___ssh_attributes(line): - ssh_dict = {} - ssh_option = (Word(alphas + '-'))('option') - ssh_value = (restOfLine)('value') - result = (ssh_option + White() + ssh_value).parseString(line) - - if result.option == 'logging': - ssh_dict['logging-events'] = 'yes' - elif result.option == 'authentication-retries': - ssh_dict['authentication_retries'] = result.value.split()[0] - elif result.option == 'port': - ssh_dict['port_rotary'] = result.value.split()[0] - elif result.option == 'maxstartups': - ssh_dict['maxstartups'] = result.value.split()[0] - elif result.option == 'time-out': - ssh_dict['time-out'] = result.value.split()[0] - elif result.option == 'version': - ssh_dict['version'] = result.value.split()[0] - - return ssh_dict - - -# Parse HTTP options -# Input: line with http option -# Sample: ip http secure-server -# Output: http option dictionary -# Sample: {'type': 'HTTPS'} -def _globalParse___http_attributes(line): - http_dict = {} - - if line == 'server': - http_dict['type'] = 'http' - elif line == 'secure-server': - http_dict['type'] = 'https' - elif line.split()[0] == 'max-connections': - http_dict['max_connections'] = line.split()[-1] - elif line.split()[0] == 'port': - http_dict['port'] = line.split()[-1] - - return http_dict - - - -# Parse console and vty line options -# Input: line with console or vty line name -# Sample: vty 0 4 -# Output: console or line options dictionary, next line (otherwise program will skip next line due to cursor placement) -# Sample: {'log_syng': 'no', 'access-class': {'name': 'ssh-in', 'type': 'in'}, 'privilege': '15'}, 'line vty 5 15' -def _globalParse___line_attributes(config): - line_list, next_line = get_attributes(config) - line_dict = {'log_syng': 'no', 'no_exec': 'no', 'access-class': {}} - - parse_login_type = Suppress('login ' + Optional('authentication ')) + restOfLine - parse_exec_timeout = Suppress('exec-timeout ') + restOfLine - parse_pass_type = Suppress('password ') + restOfLine - parse_privilege = Suppress('privilege level ') + restOfLine - parse_transp_in = Suppress('transport input ') + restOfLine - parse_transp_out = Suppress('transport output ') + restOfLine - parse_rotary = Suppress('rotary ') + restOfLine - parse_access_class = Suppress('access-class') + Word(alphas + '-') + MatchFirst(['in', 'out']) + \ - Suppress(Optional(restOfLine)) - - for option in line_list: - if option == 'logging synchronous': - line_dict['log_syng'] = 'yes' - continue - if option == 'no exec': - line_dict['no_exec'] = 'yes' - continue - try: - item = parse_exec_timeout.parseString(option).asList()[-1] - item = item.split() - if len(item) == 2: - line_dict['exec_timeout'] = int(item[0]) + int(item[1]) / 60 - else: - line_dict['exec_timeout'] = int(item[0]) - continue - except ParseException: - pass - try: - line_dict['login_type'] = parse_login_type.parseString(option).asList()[-1] - continue - except ParseException: - pass - try: - line_dict['pass_type'] = parse_pass_type.parseString(option).asList()[-1] - continue - except ParseException: - pass - try: - line_dict['privilege'] = parse_privilege.parseString(option).asList()[-1] - continue - except ParseException: - pass - try: - line_dict['transp_in'] = parse_transp_in.parseString(option).asList()[-1] - continue - except ParseException: - pass - try: - line_dict['transp_out'] = parse_transp_out.parseString(option).asList()[-1] - continue - except ParseException: - pass - try: - line_dict['rotary'] = parse_rotary.parseString(option).asList()[-1] - continue - except ParseException: - pass - try: - item = parse_access_class.parseString(option).asList() - line_dict['access-class']['name'] = item[0] - line_dict['access-class']['type'] = item[-1] - continue - except ParseException: - pass +parse_active_service = Suppress('service ') + restOfLine +parse_disable_service = Suppress('no service ') + restOfLine +parse_version = Suppress('version ') + restOfLine +parse_model = Suppress('boot system flash bootflash:') + restOfLine +parse_ipv6 = Suppress('ipv6 ') + restOfLine +parse_ipv6_sourceguard = Suppress('source-guard ') + restOfLine +parse_ipv6_snooping = Suppress('snooping ') + restOfLine +parse_ipv6_raguard = Suppress('nd raguard ') + restOfLine +parse_ipv6_destinationguard = Suppress('destination-guard ') + restOfLine +parse_ipv6_dhcpguard = Suppress('dhcp guard ') + restOfLine +parse_lldp = Suppress('lldp ') + restOfLine +parse_username = Suppress('username ') + restOfLine +parse_aaa = Suppress('aaa ') + restOfLine +parse_stp = Suppress('spanning-tree ') + restOfLine +parse_vtp = Suppress('vtp ') + restOfLine +parse_line = Suppress('line ') + restOfLine +parse_ip_ssh = Suppress('ip ssh ') + restOfLine +parse_vstack = Suppress('no') + 'vstack' + +parse_enable_password = Suppress('enable') + MatchFirst(['secret', 'password']) + Optional(Word(nums) + Suppress(White(exact=1))) + Suppress(restOfLine) +parse_ip_dhcp = NotAny(White()) + Suppress('ip dhcp snooping') + Optional(Suppress('vlan') + Word(nums) + ZeroOrMore(Suppress(',') + Word(nums))) +parse_ip_arp = NotAny(White()) + Suppress('ip arp inspection') + Suppress('vlan') + Word(nums) + ZeroOrMore(Suppress(',') + Word(nums)) +parse_ip_service = NotAny(White()) + Suppress('ip') + MatchFirst(['finger', 'identd', 'source-route', 'bootp server']) +parse_ip_http = NotAny(White()) + Suppress('ip http ') + restOfLine - return line_dict, next_line +authentication = Suppress('authentication ') + restOfLine +authorization = Suppress('authorization ') + restOfLine +accounting = Suppress('accounting ') + restOfLine # Parse global options @@ -291,30 +81,36 @@ def global_parse(config): global accounting global parse_vtp - # count_authen, count_author, count_acc = 1, 1, 1 + count_authen, count_author, count_acc = 1, 1, 1 + for line in config: if 'no cdp run' in line: iface_global['cdp'] = 1 + try: - iface_global['lldp'] = parse_lldp.parseString(line).asList()[0] + iface_global['lldp'] = parse_lldp .parseString(line).asList()[0] continue except ParseException: pass + try: iface_global['version'] = parse_version.parseString(line).asList()[0] continue except ParseException: pass + try: - iface_global['model'] = parse_model.parseString(line).asList()[0] + iface_global['model'] = parse_model .parseString(line).asList()[0] continue except ParseException: pass + try: iface_global['active_service'].append(parse_active_service.parseString(line).asList()[-1]) continue except ParseException: pass + try: curr = parse_ipv6.parseString(line).asList()[-1] try: @@ -342,19 +138,21 @@ def global_parse(config): iface_global['ipv6']['destination-guard'][tmp[0]] = tmp[1] except ParseException: pass - except ParseException: pass + try: iface_global['disable_service'].append(parse_disable_service.parseString(line).asList()[-1]) continue except ParseException: pass + try: iface_global['disable_service'].append(parse_vstack.parseString(line).asList()[-1]) continue except ParseException: pass + try: current_line = parse_enable_password.parseString(line).asList() try: @@ -365,12 +163,14 @@ def global_parse(config): continue except ParseException: pass + try: current_line = parse_username.parseString(line).asList()[-1] - iface_global['users'].update(_globalParse___username_attributes(current_line)) + iface_global['users'].update(parsing_checks.username._globalParse___username_attributes(current_line)) continue except ParseException: pass + try: vtp = parse_vtp.parseString(line).asList()[-1] result_parse_vtp = parsing_checks.vtp._globalParse___vtp_attributes(vtp, iface_global['vtp']) @@ -378,34 +178,36 @@ def global_parse(config): iface_global['vtp'] = result_parse_vtp except ParseException: pass - # try: - # current_line = parse_aaa.parseString(line).asList()[-1] - # try: - # current_line = authentication.parseString(current_line).asList()[-1] - # iface_global['aaa'].setdefault('authentication',{}) - # iface_global['aaa']['authentication'].update(_globalParse___aaa_attributes(current_line,'authentication',count_authen)) - # count_authen += 1 - # continue - # except ParseException: - # pass - # try: - # current_line = authorization.parseString(current_line).asList()[-1] - # iface_global['aaa'].setdefault('authorization',{}) - # iface_global['aaa']['authorization'].update(_globalParse___aaa_attributes(current_line,'authorization',count_author)) - # count_author += 1 - # continue - # except ParseException: - # pass - # try: - # current_line = accounting.parseString(current_line).asList()[-1] - # iface_global['aaa'].setdefault('accounting',{}) - # iface_global['aaa']['accounting'].update(_globalParse___aaa_attributes(current_line,'accounting',count_acc)) - # count_acc += 1 - # continue - # except: - # pass - # except ParseException: - # pass + + try: + current_line = parse_aaa.parseString(line).asList()[-1] + try: + current_line = authentication.parseString(current_line).asList()[-1] + iface_global['aaa'].setdefault('authentication',{}) + iface_global['aaa']['authentication'].update(parsing_checks.aaa._globalParse___aaa_attributes(current_line,'authentication',count_authen)) + count_authen += 1 + continue + except ParseException: + pass + try: + current_line = authorization.parseString(current_line).asList()[-1] + iface_global['aaa'].setdefault('authorization',{}) + iface_global['aaa']['authorization'].update(parsing_checks.aaa._globalParse___aaa_attributes(current_line,'authorization',count_author)) + count_author += 1 + continue + except ParseException: + pass + try: + current_line = accounting.parseString(current_line).asList()[-1] + iface_global['aaa'].setdefault('accounting',{}) + iface_global['aaa']['accounting'].update(parsing_checks.aaa._globalParse___aaa_attributes(current_line,'accounting',count_acc)) + count_acc += 1 + continue + except: + pass + except ParseException: + pass + try: current_line = parse_ip_dhcp.parseString(line).asList() iface_global['ip']['dhcp_snooping']['active'] = 'yes' @@ -413,6 +215,7 @@ def global_parse(config): iface_global['ip']['dhcp_snooping']['vlans'] = current_line except ParseException: pass + try: current_line = parse_ip_arp.parseString(line).asList() iface_global['ip']['arp_inspection']['active'] = 'yes' @@ -421,23 +224,27 @@ def global_parse(config): continue except ParseException: pass + try: current_line = parse_ip_ssh.parseString(line).asList()[-1] - iface_global['ip']['ssh'].update(_globalParse___ssh_attributes(current_line)) + iface_global['ip']['ssh'].update(parsing_checks.ssh._globalParse___ssh_attributes(current_line)) continue except ParseException: pass + try: iface_global['ip']['active_service'].append(parse_ip_service.parseString(line).asList()[-1]) continue except ParseException: pass + try: current_line = parse_ip_http.parseString(line).asList()[-1] - iface_global['ip']['http'].update(_globalParse___http_attributes(current_line)) + iface_global['ip']['http'].update(parsing_checks.http._globalParse___http_attributes(current_line)) continue except ParseException: pass + try: stp_str = parse_stp.parseString(line).asList()[-1] stp_line = parsing_checks.stp_global._globalParse___stp_attributes(stp_str, iface_global['stp']) @@ -446,10 +253,11 @@ def global_parse(config): continue except ParseException: pass + try: while line != '!': item = parse_line.parseString(line).asList()[-1] - iface_global['line'][item], next_line = _globalParse___line_attributes(config) + iface_global['line'][item], next_line = parsing_checks.lines._globalParse___line_attributes(config) line = next_line continue except ParseException: @@ -462,7 +270,8 @@ def global_parse(config): # Output: interface options dictionary # Sample: {'vlans': [], 'shutdown': 'no', 'description': '-= MGMT - core.nnn048.nnn =-'} def _interfaceParse___iface_attributes(config, check_disabled): - iface_list = get_attributes(config)[0] + iface_list = util.get_attributes(config)[0] + # if iface isn`t enable and unused if iface_list: iface_dict = {'shutdown': 'no', 'vlans': [], 'cdp': 'yes', 'dhcp_snoop': {'mode': 'untrust'}, @@ -470,17 +279,17 @@ def _interfaceParse___iface_attributes(config, check_disabled): 'storm control': {}, 'port-security': {}, 'ipv6': {}} vlan_num = Word(nums + '-') + ZeroOrMore(Suppress(',') + Word(nums + '-')) - parse_description = Suppress('description ') + restOfLine - parse_type = Suppress('switchport mode ') + restOfLine - parse_storm = Suppress('storm-control ') + restOfLine - parse_port_sec = Suppress('switchport port-security ') + restOfLine - parse_stp_port = Suppress('spanning-tree ') + restOfLine - parse_dhcp_snoop = Suppress('ip dhcp snooping ') + restOfLine - parse_arp_insp = Suppress('ip arp inspection ') + restOfLine - parse_source_guard = Suppress('ip verify source ') + restOfLine - parse_vlans = Suppress('switchport ') + Suppress(MatchFirst('access vlan ' + - ('trunk allowed vlan ' + Optional( - 'add ')))) + vlan_num + + parse_description = Suppress('description ') + restOfLine + parse_type = Suppress('switchport mode ') + restOfLine + parse_storm = Suppress('storm-control ') + restOfLine + parse_port_sec = Suppress('switchport port-security ') + restOfLine + parse_stp_port = Suppress('spanning-tree ') + restOfLine + parse_dhcp_snoop = Suppress('ip dhcp snooping ') + restOfLine + parse_arp_insp = Suppress('ip arp inspection ') + restOfLine + parse_source_guard = Suppress('ip verify source ') + restOfLine + + parse_vlans = Suppress('switchport ') + Suppress(MatchFirst('access vlan ' + ('trunk allowed vlan ' + Optional('add ')))) + vlan_num # Reserved options list is using due to 'shutdown' option is usually located at the end of the list, so it breaks cycle if interface is shutdown and function speed increases for option in iface_list[::-1]: diff --git a/parsing_checks/__init__.py b/parsing_checks/__init__.py index 3bc9f12..0f118d3 100644 --- a/parsing_checks/__init__.py +++ b/parsing_checks/__init__.py @@ -1 +1 @@ -__all__ = ["ip_iface","port_security","storm_control","stp_global","vtp"] \ No newline at end of file +__all__ = ["ip_iface","port_security","storm_control","stp_global","vtp","username","aaa","ssh","http","lines"] \ No newline at end of file diff --git a/parsing_checks/aaa.py b/parsing_checks/aaa.py new file mode 100644 index 0000000..32617c4 --- /dev/null +++ b/parsing_checks/aaa.py @@ -0,0 +1,38 @@ +# Parse AAA options +# Input: +# line with AAA options, type of AAA, login count +# login default group radius local, authentication, 1 +# Output: +# AAA option dictionary +# {'login1': {'list': 'default', 'methods': ['radius', 'local']}} +from pyparsing import Word,Suppress,printables,restOfLine,OneOrMore,MatchFirst,Optional + + +def _globalParse___aaa_attributes(line, type, count_aaa): + aaa_dict = {} + + parse_authentication_options = Suppress('login') + Word(printables) + OneOrMore(Optional(Suppress('group')) + Word(printables)) + parse_authorization_options = MatchFirst(['exec', 'login']) + Word(printables) + OneOrMore(Optional(Suppress('group')) + Word(printables)) + parse_accounting_options = MatchFirst(['exec', 'network']) + Word(printables) +\ + MatchFirst(['start-stop', 'stop-only', 'stop']) + OneOrMore(Optional(Suppress('group')) + Word(printables)) + + if type == 'authentication': + result = parse_authentication_options.parseString(line) + aaa_dict.update({'login' + str(count_aaa): {}}) + aaa_dict['login' + str(count_aaa)]['list'] = result.pop(0) + aaa_dict['login' + str(count_aaa)]['methods'] = result.asList() + elif type == 'authorization': + result = parse_authorization_options.parseString(line) + aaa_dict.update({'login' + str(count_aaa): {}}) + aaa_dict['login' + str(count_aaa)]['login'] = result.pop(0) + aaa_dict['login' + str(count_aaa)]['list'] = result.pop(0) + aaa_dict['login' + str(count_aaa)]['methods'] = result.asList() + elif type == 'accounting': + result = parse_accounting_options.parseString(line) + aaa_dict.update({'login' + str(count_aaa): {}}) + aaa_dict['login' + str(count_aaa)]['login'] = result.pop(0) + aaa_dict['login' + str(count_aaa)]['list'] = result.pop(0) + aaa_dict['login' + str(count_aaa)]['record'] = result.pop(0) + aaa_dict['login' + str(count_aaa)]['methods'] = result.asList() + + return aaa_dict diff --git a/parsing_checks/http.py b/parsing_checks/http.py new file mode 100644 index 0000000..b68cc32 --- /dev/null +++ b/parsing_checks/http.py @@ -0,0 +1,20 @@ +# Parse HTTP options +# Input: +# line with http option +# ip http secure-server +# Output: +# http option dictionary +# {'type': 'HTTPS'} +def _globalParse___http_attributes(line): + http_dict = {} + + if line == 'server': + http_dict['type'] = 'http' + elif line == 'secure-server': + http_dict['type'] = 'https' + elif line.split()[0] == 'max-connections': + http_dict['max_connections'] = line.split()[-1] + elif line.split()[0] == 'port': + http_dict['port'] = line.split()[-1] + + return http_dict diff --git a/parsing_checks/lines.py b/parsing_checks/lines.py new file mode 100644 index 0000000..06a575c --- /dev/null +++ b/parsing_checks/lines.py @@ -0,0 +1,80 @@ +# Parse console and vty line options +# Input: +# line with console or vty line name +# vty 0 4 +# Output: +# console or line options dictionary, next line (otherwise program will skip next line due to cursor placement) +# {'log_syng': 'no', 'access-class': {'name': 'ssh-in', 'type': 'in'}, 'privilege': '15'}, 'line vty 5 15' +import util +from pyparsing import Word,alphas,MatchFirst,restOfLine,Suppress,Optional,ParseException + + +def _globalParse___line_attributes(config): + line_list, next_line = util.get_attributes(config) + line_dict = {'log_syng': 'no', 'no_exec': 'no', 'access-class': {}} + + parse_login_type = Suppress('login ' + Optional('authentication ')) + restOfLine + parse_exec_timeout = Suppress('exec-timeout ') + restOfLine + parse_pass_type = Suppress('password ') + restOfLine + parse_privilege = Suppress('privilege level ') + restOfLine + parse_transp_in = Suppress('transport input ') + restOfLine + parse_transp_out = Suppress('transport output ') + restOfLine + parse_rotary = Suppress('rotary ') + restOfLine + parse_access_class = Suppress('access-class') + Word(alphas + '-') + MatchFirst(['in', 'out']) + Suppress(Optional(restOfLine)) + + for option in line_list: + if option == 'logging synchronous': + line_dict['log_syng'] = 'yes' + continue + if option == 'no exec': + line_dict['no_exec'] = 'yes' + continue + try: + item = parse_exec_timeout.parseString(option).asList()[-1] + item = item.split() + if len(item) == 2: + line_dict['exec_timeout'] = int(item[0]) + int(item[1]) / 60 + else: + line_dict['exec_timeout'] = int(item[0]) + continue + except ParseException: + pass + try: + line_dict['login_type'] = parse_login_type.parseString(option).asList()[-1] + continue + except ParseException: + pass + try: + line_dict['pass_type'] = parse_pass_type .parseString(option).asList()[-1] + continue + except ParseException: + pass + try: + line_dict['privilege'] = parse_privilege .parseString(option).asList()[-1] + continue + except ParseException: + pass + try: + line_dict['transp_in'] = parse_transp_in .parseString(option).asList()[-1] + continue + except ParseException: + pass + try: + line_dict['transp_out'] = parse_transp_out.parseString(option).asList()[-1] + continue + except ParseException: + pass + try: + line_dict['rotary'] = parse_rotary .parseString(option).asList()[-1] + continue + except ParseException: + pass + try: + item = parse_access_class.parseString(option).asList() + line_dict['access-class']['name'] = item[0] + line_dict['access-class']['type'] = item[-1] + continue + except ParseException: + pass + + return line_dict, next_line diff --git a/parsing_checks/ssh.py b/parsing_checks/ssh.py new file mode 100644 index 0000000..2391b9f --- /dev/null +++ b/parsing_checks/ssh.py @@ -0,0 +1,32 @@ +# Parse SSH options +# Input: +# line with ssh option +# ip ssh time-out 30 +# Output: +# ssh option dictionary +# {'time-out': '30'} +from pyparsing import Word,alphas,White,restOfLine + + +def _globalParse___ssh_attributes(line): + ssh_dict = {} + + ssh_option = (Word(alphas + '-'))('option') + ssh_value = (restOfLine) ('value') + + result = (ssh_option + White() + ssh_value).parseString(line) + + if result.option == 'logging': + ssh_dict['logging-events'] = 'yes' + elif result.option == 'authentication-retries': + ssh_dict['authentication_retries'] = result.value.split()[0] + elif result.option == 'port': + ssh_dict['port_rotary'] = result.value.split()[0] + elif result.option == 'maxstartups': + ssh_dict['maxstartups'] = result.value.split()[0] + elif result.option == 'time-out': + ssh_dict['time-out'] = result.value.split()[0] + elif result.option == 'version': + ssh_dict['version'] = result.value.split()[0] + + return ssh_dict diff --git a/parsing_checks/username.py b/parsing_checks/username.py new file mode 100644 index 0000000..bd1a06c --- /dev/null +++ b/parsing_checks/username.py @@ -0,0 +1,30 @@ +# Parse username options +# Input: +# line with user options +# vasya privilege 15 secret 5 $1$0k5Q$3h/ZPjj8T0iHu9DL/Ejt30 +# Output: +# user's options dictionary +# {'vasya': {'password_type': '5', 'privilege': '15'}} +from pyparsing import Word,Suppress,printables,restOfLine,nums,MatchFirst,Optional + + +def _globalParse___username_attributes(line): + username_dict = {} + + username = (Word(printables)) ('user') + privilege = (Suppress('privilege') + Word(nums)) ('priv_num') + password_type = (Suppress(MatchFirst(['secret', 'password'])) + Word(nums))('pass_type') + + parse_username = username + Optional(privilege) + password_type + Suppress(restOfLine) + + result = parse_username.parseString(line) + + username_dict[result.user] = {} + username_dict[result.user]['password_type'] = result.pass_type.asList()[0] + + try: + username_dict[result.user]['privilege'] = result.priv_num.asList()[0] + except AttributeError: + pass + + return username_dict diff --git a/util.py b/util.py index 3f4d1ad..d50b413 100644 --- a/util.py +++ b/util.py @@ -1,4 +1,5 @@ # library with different useful functions to use them within various modules +from pyparsing import White,restOfLine,Suppress,Optional # converts string list of numbers to list of ints with those numbers # ['1','2','3'] -> [1,2,3] @@ -14,4 +15,26 @@ def int_dict_parse(parse_meth,featur_str,name,featur_dict): value = parse_meth.parseString(featur_str).asList() featur_dict[name] = value - return featur_dict \ No newline at end of file + return featur_dict + + +# Parse any attributes with whitespace as first symbol into list +# Input: +# line with futher options (starts with whitespaces) +# interface Loopback1 +# Output: +# further options list, next line (otherwise program may skip next line due to cursor placement) +# ['description -= MGMT - core.nnn048.nnn =-', 'ip address 172.21.24.140 255.255.255.255'], '!' +def get_attributes(config): + options_list = [] + option = White(exact=1) + Suppress(Optional(White())) + restOfLine + next_line = config.readline() + try: + option_parse = option.parseString(next_line) + while option_parse[0] == ' ': + options_list.append(option_parse[-1]) + next_line = config.readline() + option_parse = option.parseString(next_line) + except: + pass + return options_list, next_line