def get_scan_results(self): scan_file = None for i in range(self.scan_notebook.get_n_pages()): sbook_page = self.scan_notebook.get_nth_page(i) if not sbook_page.status.get_empty(): scan_file = sbook_page.parsed.nmap_xml_file if hasattr(scan_file, "name"): # this scan was loaded from a file so nmap_xml_file is # actually a file object, but we are interested only in # the file name. scan_file = scan_file.name if scan_file and os.access(scan_file, os.R_OK) and os.path.isfile(scan_file): log.debug(">>> Retrieving unsaved scan result: %s" % scan_file) try: parsed = NmapParser() parsed.set_xml_file(scan_file) parsed.parse() parsed.set_scan_name("Unsaved " + sbook_page.get_tab_label()) parsed.set_unsaved() except: pass else: yield parsed
def match_port(self, port): log.debug("Match port:%s" % port) if port == [""] or port == ["*"]: return True ports = [] for p in self.parsed_scan.ports: for port_dic in p: for portid in port_dic["port"]: if self.port_open and portid["port_state"] == "open": ports.append(portid["portid"]) elif self.port_filtered and portid["port_state"] == "filtered": ports.append(portid["portid"]) elif self.port_closed and portid["port_state"] == "closed": ports.append(portid["portid"]) elif not self.port_open and not self.port_filtered and not self.port_closed: # In case every port state is False, add every port ports.append(portid["portid"]) for keyport in port: if keyport not in ports: return False # No match for asked port else: return True # Every given port matched current result
def get_scan_results(self): scan_file = None for i in range(self.scan_notebook.get_n_pages()): sbook_page = self.scan_notebook.get_nth_page(i) if not sbook_page.status.get_empty(): scan_file = sbook_page.parsed.nmap_xml_file if hasattr(scan_file, "name"): # this scan was loaded from a file so nmap_xml_file is # actually a file object, but we are interested only in # the file name. scan_file = scan_file.name if scan_file and os.access(scan_file, os.R_OK) and\ os.path.isfile(scan_file): log.debug(">>> Retrieving unsaved scan result: %s" % scan_file) try: parsed = NmapParser() parsed.set_xml_file(scan_file) parsed.parse() parsed.set_scan_name("Unsaved " + \ sbook_page.get_tab_label()) parsed.set_unsaved() except: pass else: yield parsed
def match_port(self, port): log.debug("Match port:%s" % port) if port == [""] or port == ["*"]: return True ports = [] for p in self.parsed_scan.ports: for port_dic in p: for portid in port_dic["port"]: if self.port_open and portid["port_state"] == "open": ports.append(portid["portid"]) elif self.port_filtered and\ portid["port_state"] == "filtered": ports.append(portid["portid"]) elif self.port_closed and portid["port_state"] == "closed": ports.append(portid["portid"]) elif not self.port_open and \ not self.port_filtered and \ not self.port_closed: # In case every port state is False, add every port ports.append(portid["portid"]) for keyport in port: if keyport not in ports: return False # No match for asked port else: return True # Every given port matched current result
def sanity_settings(self, settings): log.debug(">>> Sanitize %s" % str(settings)) tuple_regex = "[\(\[]\s?(\d+)\s?,\s?(\d+)\s?,\s?(\d+)\s?[\)\]]" if type(settings) == type(""): settings = [int(t) for t in re.findall(tuple_regex, settings)[0]] return settings
def match_osmatch(self, osmatch): log.debug("Match osmatch: %s" % osmatch) if osmatch == "" or osmatch == "*": return True for host in self.parsed_scan.hosts: match = host.osmatch.get("name", False) if match and fnmatch(match.lower(), "*%s*" % osmatch.lower()): return True return False
def get_filtered_ports(self): ports = 0 for h in self.nmap.get('hosts', []): ports += h.get_filtered_ports() log.debug(">>> EXTRAPORTS: %s" % str(self.list_extraports)) return ports
def match_profile(self, profile): log.debug("Match profile: %s" % profile) log.debug("Comparing: %s == %s ??" % (str(self.parsed_scan.profile_name).lower(), "*%s*" % profile.lower())) if ( profile == "*" or profile == "" or fnmatch(str(self.parsed_scan.profile_name).lower(), "*%s*" % profile.lower()) ): return True # Pattern matches return False # Pattern doesn't match
def __init__(self, search_directory, file_extensions=["usr"]): SearchResult.__init__(self) log.debug(">>> SearchDir initialized") self.search_directory = search_directory if type(file_extensions) in StringTypes: self.file_extensions = file_extensions.split(";") elif type(file_extensions) == type([]): self.file_extensions = file_extensions else: raise Exception("Wrong file extension format! '%s'" % file_extensions)
def match_profile(self, profile): log.debug("Match profile: %s" % profile) log.debug("Comparing: %s == %s ??" % \ (str(self.parsed_scan.profile_name).lower(), "*%s*" % profile.lower())) if profile == "*" or profile == "" or \ fnmatch(str(self.parsed_scan.profile_name).lower(), "*%s*" % profile.lower()): return True # Pattern matches return False # Pattern doesn't match
def root_dir(self): """Retrieves root dir on current filesystem""" curr_dir = getcwd() while True: splited = split(curr_dir)[0] if curr_dir == splited: break curr_dir = splited log.debug(">>> Root dir: %s" % curr_dir) return curr_dir
def check_version(self, config_dir): version_file = join(config_dir, base_paths['umit_version']) if exists(version_file): ver = open(version_file).readline().strip() log.debug(">>> This Umit Version: %s" % VERSION) log.debug(">>> Version of the files in %s: %s" % (config_dir, ver)) if VERSION == ver: return True return False
def parse(self): if self.nmap_xml_file: if type(self.nmap_xml_file) in StringTypes: self.parser.parse(self.nmap_xml_file) else: log.debug(">>> XML content: %s" % self.nmap_xml_file.read()) self.nmap_xml_file.seek(0) self.parser.parse(self.nmap_xml_file) # Closing file to avoid problems with file descriptors self.nmap_xml_file.close() else: raise Exception("There's no file to be parsed!")
def match_keyword(self, keyword): log.debug("Match keyword: %s" % keyword) if self.match_profile(keyword) or \ self.match_option(keyword) or \ self.match_target(keyword) or \ self.match_mac(keyword) or \ self.match_ipv4(keyword) or \ self.match_ipv6(keyword) or \ self.match_service(keyword) or \ self.match_osmatch(keyword) or \ self.match_product(keyword) or \ self.basic_match(keyword, "nmap_output") or \ self.basic_match(keyword, "profile_name"): return True
def copy_config_file(filename, dir_origin, dir_destiny): log.debug(">>> copy_config_file %s to %s" % (filename, dir_destiny)) origin = join(dir_origin, filename) destiny = join(dir_destiny, filename) if not exists(destiny): # Quick copy origin_file = open(origin, 'r') destiny_file = open(destiny, 'w') destiny_file.write(origin_file.read()) origin_file.close() destiny_file.close() return destiny
def search(self, **kargs): log.debug(">>> Starting search process...") parameters = [ "keyword", "profile", "option", "target", "mac", "ipv4", "ipv6", "port", "service", "osclass", "osmatch", "product", ] # If nothing is passed, let's considerate that we want to search # every port self.port_closed = kargs.get("port_closed", True) self.port_open = kargs.get("port_open", True) self.port_filtered = kargs.get("port_filtered", True) # Iterate over scan results searching for patterns # Obs: This search looks for a result that matches each received # parameters ("and" based search). If something fail, it # desconsiderates the result keys = kargs.keys() # Catch given parameters names log.debug(">>> Search parameters: %s" % keys) # Get parsed results, as NmapParser objects for scan_result in self.get_scan_results(): self.parsed_scan = scan_result # Test each given parameter against current parsed result for parameter in parameters: if parameter in keys: log.debug(">>> Searching '%s' at '%s'" % (parameter, kargs[parameter])) if not self.__getattribute__("match_%s" % parameter)(kargs[parameter]): # A break here, means that there is no match for the # given pattern and, as it is an "and" based search, the # parsed result must be discarted log.debug(">>> Parsed result doesn't match patterns!") break else: log.debug(">>> Parsed result matches given patterns!") yield self.parsed_scan
def match_service(self, service): log.debug("Match service: %s" % service) if service == "" or service == "*": return True services = [] for first in self.parsed_scan.ports: for ports in first: for port in ports["port"]: if port.has_key('service_name'): if port["service_name"] not in services: services.append(port["service_name"]) if service in services: return True # Given service name matched current result return False # Given service name didn't match current result
def match_keyword(self, keyword): log.debug("Match keyword: %s" % keyword) if ( self.match_profile(keyword) or self.match_option(keyword) or self.match_target(keyword) or self.match_mac(keyword) or self.match_ipv4(keyword) or self.match_ipv6(keyword) or self.match_service(keyword) or self.match_osmatch(keyword) or self.match_product(keyword) or self.basic_match(keyword, "nmap_output") or self.basic_match(keyword, "profile_name") ): return True
def match_service(self, service): log.debug("Match service: %s" % service) if service == "" or service == "*": return True services = [] for first in self.parsed_scan.ports: for ports in first: for port in ports["port"]: if port.has_key("service_name"): if port["service_name"] not in services: services.append(port["service_name"]) if service in services: return True # Given service name matched current result return False # Given service name didn't match current result
def match_product(self, product): log.debug("Match product: %s" % product) if product == "" or product == "*": return True products = [] for first in self.parsed_scan.ports: for ports in first: for port in ports["port"]: if fnmatch(port.get("service_product", "").lower(), "*%s*" % product.lower()): # Given service product matched current result return True # Given service product didn't match current result return False
def sendmail(self, subject, msg, attach=False): try: self.email_server except AttributeError: self.connect() try: mail = self.create_mail(subject, msg, attach) log.debug(">>> SENDMAIL \n%s" % mail.as_string()) self.email_server.sendmail(self.from_addr, self.to_addr, mail.as_string()) log.debug(">>> SENT!") return True except sslerror: return True
def add_profile(self, profile_name, **attributes): log.debug(">>> Add Profile '%s': %s" % (profile_name, attributes)) try: self.add_section(profile_name) except: return None [self._set_it(profile_name, attr, attributes[attr]) \ for attr in attributes if attr != "options"] options = attributes["options"] if type(options) in StringTypes: self._set_it(profile_name, "options", options) elif type(options) == type({}): self._set_it(profile_name, "options", ",".join(options.keys())) for opt in options: if options[opt]: self._set_it(profile_name, opt, options[opt]) self.save_changes()
def get_config_file(filename, original_content): config_file = mktemp() try: c = Path.__getattr__(filename) if exists(c) and access(c, R_OK): config_file = c else: raise Exception() except: # Using temporary file cfile = open(config_file, "w") cfile.write(original_content) cfile.close() log.debug(">>> Get config file %s: %s" % (filename, config_file)) return config_file
def match_product(self, product): log.debug("Match product: %s" % product) if product == "" or product == "*": return True products = [] for first in self.parsed_scan.ports: for ports in first: for port in ports["port"]: if fnmatch( port.get("service_product", "").lower(), "*%s*" % product.lower()): # Given service product matched current result return True # Given service product didn't match current result return False
def cleanup(self, save_time): log.debug(">>> Cleanning up data base.") log.debug(">>> Removing results olders than %s seconds" % save_time) self.cursor.execute("SELECT scans_id FROM scans WHERE date < ?", (time() - save_time,)) for sid in [sid[0] for sid in self.cursor.fetchall()]: log.debug(">>> Removing results with scans_id %s" % sid) self.cursor.execute("DELETE FROM scans WHERE scans_id = ?", (sid, )) else: connection.commit() log.debug(">>> Data base sucessfully cleanned up!")
def kill(self): log.debug(">>> Killing scan process %s" % self.command_process.pid) if sys.platform != "win32": try: from signal import SIGKILL os.kill(self.command_process.pid, SIGKILL) except: pass else: try: # Not sure if this works. Must research a bit more about this # subprocess's method to see how it works. # In the meantime, this should not raise any exception because # we don't care if it killed the process as it never killed # it anyway. from subprocess import TerminateProcess TerminateProcess(self.command_process._handle, 0) except: pass
def cleanup(self, save_time): log.debug(">>> Cleanning up data base.") log.debug(">>> Removing results olders than %s seconds" % save_time) self.cursor.execute("SELECT scans_id FROM scans WHERE date < ?", (time() - save_time, )) for sid in [sid[0] for sid in self.cursor.fetchall()]: log.debug(">>> Removing results with scans_id %s" % sid) self.cursor.execute("DELETE FROM scans WHERE scans_id = ?", (sid, )) else: connection.commit() log.debug(">>> Data base sucessfully cleanned up!")
def search(self, **kargs): log.debug(">>> Starting search process...") parameters = [ "keyword", "profile", "option", "target", "mac", "ipv4", "ipv6", "port", "service", "osclass", "osmatch", "product" ] # If nothing is passed, let's considerate that we want to search # every port self.port_closed = kargs.get("port_closed", True) self.port_open = kargs.get("port_open", True) self.port_filtered = kargs.get("port_filtered", True) # Iterate over scan results searching for patterns # Obs: This search looks for a result that matches each received # parameters ("and" based search). If something fail, it # desconsiderates the result keys = kargs.keys() # Catch given parameters names log.debug(">>> Search parameters: %s" % keys) # Get parsed results, as NmapParser objects for scan_result in self.get_scan_results(): self.parsed_scan = scan_result # Test each given parameter against current parsed result for parameter in parameters: if parameter in keys: log.debug(">>> Searching '%s' at '%s'" % (parameter, kargs[parameter])) if not self.__getattribute__("match_%s" % parameter)\ (kargs[parameter]): # A break here, means that there is no match for the # given pattern and, as it is an "and" based search, the # parsed result must be discarted log.debug(">>> Parsed result doesn't match patterns!") break else: log.debug(">>> Parsed result matches given patterns!") yield self.parsed_scan
def match_osclass(self, osclass): log.debug("Match osclass: %s" % osclass) if osclass == "" or osclass == "*": return True class_info = self.split_osclass(osclass) log.debug("Class info: %s" % class_info) for host in self.parsed_scan.hosts: for oc in host.osclasses: #log.debug("Vendor: %s" % oc.get("vendor", "")) #log.debug("OS Family: %s" % oc.get("osfamily", "")) #log.debug("OS Gen: %s" % oc.get("osgen", "")) #log.debug("Type: %s" % oc.get("type", "")) if oc.get("vendor", "").lower() == class_info[0] and \ oc.get("osfamily", "").lower() == class_info[1] and \ oc.get("osgen", "").lower() == class_info[2] and \ oc.get("type", "").lower() == class_info[3]: return True # Found a match return False
def create_user_dir(config_file, user_home): log.debug(">>> Create user dir at given home: %s" % user_home) log.debug(">>> Using %s as source" % config_file) main_umit_conf = UmitConfigParser() main_umit_conf.read(config_file) paths_section = "paths" user_dir = join(user_home, base_paths['config_dir']) if exists(user_home)\ and access(user_home, R_OK and W_OK)\ and not exists(user_dir): mkdir(user_dir) log.debug(">>> Umit user dir successfully created! %s" % user_dir) else: log.warning(">>> No permissions to create user dir!") return False main_dir = split(config_file)[0] copy_config_file("options.xml", main_dir, user_dir) copy_config_file("profile_editor.xml", main_dir, user_dir) copy_config_file("scan_profile.usp", main_dir, user_dir) copy_config_file("umit_version", main_dir, user_dir) copy_config_file("wizard.xml", main_dir, user_dir) return dict(user_dir = user_dir, config_dir = user_dir, config_file = copy_config_file("umit.conf", split(config_file)[0], user_dir))
def get_scan_results(self): log.debug(">>> Getting scan results stored in data base") u = UmitDB() for scan in u.get_scans(): log.debug(">>> Retrieving result of scans_id %s" % scan.scans_id) log.debug(">>> Nmap xml output: %s" % scan.nmap_xml_output) temp_file = mktemp(".usr", "umit_") tmp = open(temp_file, "w") tmp.write(scan.nmap_xml_output) tmp.close() try: parsed = NmapParser() parsed.set_xml_file(temp_file) parsed.parse() # Remove temporary file reference parsed.nmap_xml_file = "" except: pass else: yield parsed
def __init__(self, **kargs): Table.__init__(self, "scans") if "scans_id" in kargs.keys(): self.scans_id = kargs["scans_id"] else: log.debug(">>>Ceating new scan result entry at data base") fields = ["scan_name", "nmap_xml_output", "date"] for k in kargs.keys(): if k not in fields: raise Exception("Wrong table field passed to creation \ method. '%s'" % k) if "nmap_xml_output" not in kargs.keys() or \ not kargs["nmap_xml_output"]: raise Exception("Can't save result without xml output") if not self.verify_digest(md5.new(kargs["nmap_xml_output"]).\ hexdigest()): raise Exception("XML output registered already!") self.scans_id = self.insert(**kargs)
def match_osclass(self, osclass): log.debug("Match osclass: %s" % osclass) if osclass == "" or osclass == "*": return True class_info = self.split_osclass(osclass) log.debug("Class info: %s" % class_info) for host in self.parsed_scan.hosts: for oc in host.osclasses: # log.debug("Vendor: %s" % oc.get("vendor", "")) # log.debug("OS Family: %s" % oc.get("osfamily", "")) # log.debug("OS Gen: %s" % oc.get("osgen", "")) # log.debug("Type: %s" % oc.get("type", "")) if ( oc.get("vendor", "").lower() == class_info[0] and oc.get("osfamily", "").lower() == class_info[1] and oc.get("osgen", "").lower() == class_info[2] and oc.get("type", "").lower() == class_info[3] ): return True # Found a match return False
def __init__(self, command=None): self.xml_output = mktemp() self.normal_output = mktemp() self.stdout_output = mktemp() self.stderr_output = mktemp() log.debug(">>> Created temporary files:") log.debug(">>> XML OUTPUT: %s" % self.xml_output) log.debug(">>> NORMAL OUTPUT: %s" % self.normal_output) log.debug(">>> STDOUT OUTPUT: %s" % self.stdout_output) log.debug(">>> STDERR OUTPUT: %s" % self.stderr_output) # Creating files. Avoid troubles while running at Windows open(self.xml_output,'w').close() open(self.normal_output,'w').close() open(self.stdout_output,'w').close() open(self.stderr_output,'w').close() self.command_process = None self.command_buffer = "" self.command_stderr = "" if command: self.command = command
def __init__(self, command=None): self.xml_output = mktemp() self.normal_output = mktemp() self.stdout_output = mktemp() self.stderr_output = mktemp() log.debug(">>> Created temporary files:") log.debug(">>> XML OUTPUT: %s" % self.xml_output) log.debug(">>> NORMAL OUTPUT: %s" % self.normal_output) log.debug(">>> STDOUT OUTPUT: %s" % self.stdout_output) log.debug(">>> STDERR OUTPUT: %s" % self.stderr_output) # Creating files. Avoid troubles while running at Windows open(self.xml_output, 'w').close() open(self.normal_output, 'w').close() open(self.stdout_output, 'w').close() open(self.stderr_output, 'w').close() self.command_process = None self.command_buffer = "" self.command_stderr = "" if command: self.command = command
def get_scan_results(self): log.debug(">>> Getting directory's scan results") files = [] for ext in self.file_extensions: files += glob(os.path.join(self.search_directory, "*.%s" % ext)) log.debug(">>> Scan results at selected directory: %s" % files) for scan_file in files: log.debug(">>> Retrieving scan result %s" % scan_file) if os.access(scan_file, os.R_OK) and os.path.isfile(scan_file): try: parsed = NmapParser() parsed.set_xml_file(scan_file) parsed.parse() except: pass else: yield parsed
# shell_state = True avoids python to open a terminal to execute nmap.exe # shell_state = False is needed to run correctly at Linux shell_state = (sys.platform == "win32") #nmap_command_path = "nmap" # Don't need the line below anymore #if sys.platform == "win32": # nmap_command_path = os.path.join(os.path.split(os.path.abspath(\ # sys.executable))[0], "Nmap", "nmap.exe") #else: nmap_command_path = "nmap" nmap_command_path = Path.nmap_command_path if not os.path.exists(nmap_command_path): nmap_command_path = "nmap" log.debug(">>> Platform: %s" % sys.platform) log.debug(">>> Nmap command path: %s" % nmap_command_path) def split_quoted(s): """Like str.split, except that no splits occur inside quoted strings, and quoted strings are unquoted.""" return [x.replace("\"", "") for x in re.findall('((?:"[^"]*"|[^"\s]+)+)', s)] class NmapCommand(object): def __init__(self, command=None): self.xml_output = mktemp() self.normal_output = mktemp() self.stdout_output = mktemp() self.stderr_output = mktemp()
def read(self, filename): log.debug(">>> Trying to parse: %s" % filename) self.filenames = ConfigParser.read(self, filename) return self.filenames
def match_ipv6(self, ipv6): log.debug("Match IPv6: %s" % ipv6) return self.basic_match(ipv6, "ipv6")
def __init__(self): SearchResult.__init__(self) log.debug(">>> SearchDB initialized")
def set_umit_conf(self, base_dir): main_config_dir = "" main_config_file = "" if exists(CONFIG_DIR) and \ exists(join(CONFIG_DIR, base_paths['config_file'])): main_config_dir = CONFIG_DIR elif exists(join(base_dir, CONFIG_DIR)) and\ exists(join(base_dir, CONFIG_DIR, base_paths['config_file'])): main_config_dir = join(base_dir, CONFIG_DIR) elif exists(join(split(base_dir)[0], CONFIG_DIR)) and \ exists(join(split(base_dir)[0], CONFIG_DIR, base_paths['config_file'])): main_config_dir = join(split(base_dir)[0], CONFIG_DIR) else: main_config_dir = create_temp_conf_dir(VERSION) # Main config file, based on the main_config_dir got above main_config_file = join(main_config_dir, base_paths['config_file']) # This is the expected place in which umit.conf should be placed supposed_file = join(base_paths['user_dir'], base_paths['config_file']) config_dir = "" config_file = "" if exists(supposed_file)\ and check_access(supposed_file, R_OK and W_OK): config_dir = base_paths['user_dir'] config_file = supposed_file log.debug(">>> Using config files in user home directory: %s" \ % config_file) elif not exists(supposed_file)\ and not check_access(base_paths['user_dir'], R_OK and W_OK): try: result = create_user_dir(join(main_config_dir, base_paths['config_file']), HOME) if type(result) == type({}): config_dir = result['config_dir'] config_file = result['config_file'] log.debug(">>> Using recently created config files in \ user home: %s" % config_file) else: raise Exception() except: log.debug(">>> Failed to create user home") if config_dir and config_file: # Checking if the version of the configuration files are the same # as this Umit's version if not self.check_version(config_dir): log.debug(">>> The config files versions are different!") log.debug(">>> Running update scripts...") self.update_config_dir(config_dir) else: log.debug(">>> There is no way to create nor use home connfigs.") log.debug(">>> Trying to use main configuration files...") config_dir = main_config_dir config_file = main_config_file # Parsing the umit main config file self.config_parser.read(config_file) # Should make the following only after reading the umit.conf file self.config_dir = config_dir self.config_file = config_file self.config_file_set = True self.locale_dir = LOCALE_DIR self.pixmaps_dir = PIXMAPS_DIR self.icons_dir = ICONS_DIR self.misc_dir = MISC_DIR self.docs_dir = DOCS_DIR log.debug(">>> Config file: %s" % config_file) log.debug(">>> Locale: %s" % self.locale_dir) log.debug(">>> Pixmaps: %s" % self.pixmaps_dir) log.debug(">>> Icons: %s" % self.icons_dir) log.debug(">>> Misc: %s" % self.misc_dir) log.debug(">>> Docs: %s" % self.docs_dir)
def connect(self): log.debug(">>> Connecting to smtp server at %s:%s as %s" \ % (self.server, self.port, self.localdomain)) self.email_server = SMTP(self.server, self.port, self.localdomain) log.debug(">>> Connected!") log.debug(">>> EHLO %s" % self.from_addr) self.email_server.ehlo(self.from_addr) if self.tls: log.debug(">>> STARTTLS") self.email_server.starttls() log.debug(">>> EHLO %s" % self.from_addr) self.email_server.ehlo(self.from_addr) if self.login_passwd: log.debug(">>> LOGIN %s@%s" % (self.login, self.login_passwd)) self.email_server.login(self.login, self.login_passwd)