| 1 |  |  | # -*- coding: utf-8 -*- | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  | # Copyright (C) 2018-2019 Greenbone Networks GmbH | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | # | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | # SPDX-License-Identifier: GPL-3.0-or-later | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | # | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | # This program is free software: you can redistribute it and/or modify | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | # it under the terms of the GNU General Public License as published by | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | # the Free Software Foundation, either version 3 of the License, or | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | # (at your option) any later version. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | # | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | # This program is distributed in the hope that it will be useful, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | # GNU General Public License for more details. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | # | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | # You should have received a copy of the GNU General Public License | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | # along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | import sys | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | from gvm.protocols.gmpv9.types import get_alive_test_from_string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | from lxml import etree | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | def check_args(args): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |     len_args = len(args.script) - 1 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |     if len_args != 1: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |         message = """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |         This script pulls target data from an xml document and feeds it to \ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |     a desired GSM | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |         One parameter after the script name is required. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |         1. <xml_doc>  -- .xml file containing targets | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |         Example: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |             $ gvm-script --gmp-username name --gmp-password pass \ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |     ssh --hostname <gsm> scripts/send-targets.gmp.py example_file.xml | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |         print(message) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |         quit() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |  | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 42 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 43 |  |  | def error_and_exit(msg): | 
            
                                                                        
                            
            
                                    
            
            
                | 44 |  |  |     print("Error: {}\n".format(msg), file=sys.stderr) | 
            
                                                                        
                            
            
                                    
            
            
                | 45 |  |  |     sys.exit(1) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  | def yes_or_no(question): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |     reply = str(input(question + ' (y/n): ')).lower().strip() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |     if reply[0] == ('y'): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |         return True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |     if reply[0] == ('n'): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |         return False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |     else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |         return yes_or_no("Please enter 'y' or 'n'") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  | def create_xml_tree(xml_doc): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |     try: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |         xml_tree = etree.parse(xml_doc) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |         xml_tree = xml_tree.getroot() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |     except IOError as err: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |         error_and_exit("Failed to read xml_file: {} (exit)".format(str(err))) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |     except etree.Error as err: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |         error_and_exit("Failed to parse xml_file: {} (exit)".format(str(err))) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |     if len(xml_tree) == 0: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |         error_and_exit("XML file is empty (exit)") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |     return xml_tree | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  | def parse_send_xml_tree(gmp, xml_tree): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |     credential_options = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |         'ssh_credential', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |         'smb_credential', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |         'esxi_credential', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |         'snmp_credential', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |     ] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |     counter = 1 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |     for target in xml_tree.xpath('target'): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |         keywords = {}  # {'make_unique': True} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |         keywords['name'] = target.find('name').text | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |         keywords['hosts'] = target.find('hosts').text.split(',') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |         exclude_hosts = target.find('exclude_hosts').text | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |         if exclude_hosts is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |             keywords['exclude_hosts'] = exclude_hosts.split(',') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |         comment = target.find('comment').text | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |         if comment is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |             keywords['comment'] = comment | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |         credentials = gmp.get_credentials()[0].xpath("//credential/@id") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |         for credential in credential_options: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |             cred_id = target.find(credential).xpath('@id')[0] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |             if cred_id == '': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |                 continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |             if cred_id not in credentials: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |                 response = yes_or_no( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |                     "\nThe credential '{}' for 'target {}' could not be " | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |                     "located...\nWould you like to continue?".format( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |                         credential, counter | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |                     ) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |                 ) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |                 if response is False: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |                     print("Terminating...\n") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |                     quit() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |                 else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |                     continue | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |             key = '{}_id'.format(credential) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |             keywords[key] = cred_id | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |             elem_path = target.find(credential) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |             port = elem_path.find('port') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |             if port is not None and port.text is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |                 port_key = '{}_port'.format(credential) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |                 keywords[port_key] = elem_path.find('port').text | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |         alive_test = get_alive_test_from_string(target.find('alive_tests').text) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |         if alive_test is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |             keywords['alive_test'] = alive_test | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |         reverse_lookup_only = target.find('reverse_lookup_only').text | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |         if reverse_lookup_only == '1': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |             keywords['reverse_lookup_only'] = 1 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |         reverse_lookup_unify = target.find('reverse_lookup_unify').text | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |         if reverse_lookup_unify == '1': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |             keywords['reverse_lookup_unify'] = 1 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |         port_range = target.find('port_range') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |         if port_range is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |             keywords['port_range'] = port_range.text | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |         if target.xpath('port_list/@id') is not None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |             port_list = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |             port_list = target.xpath('port_list/@id')[0] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |             keywords['port_list_id'] = port_list | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |         print(keywords) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |         gmp.create_target(**keywords) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |         counter += 1 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  | def main(gmp, args): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  |     # pylint: disable=undefined-variable | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |     check_args(args) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |     xml_doc = args.script[1] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  |     print('\nSending targets...') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  |     xml_tree = create_xml_tree(xml_doc) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  |     parse_send_xml_tree(gmp, xml_tree) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |     print('\n  Target(s) created!\n') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  | if __name__ == '__gmp__': | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 170 |  |  |     main(gmp, args)  # pylint: disable=undefined-variable | 
                            
                    |  |  |  | 
                                                                                        
                                                                                            
                                                                                     | 
            
                                                        
            
                                    
            
            
                | 171 |  |  |  |