Halberd.shell

Package Halberd :: Module shell |
[hide private]
[frames] | no frames]

# Source Code for Module Halberd.shell

      1  # -*- coding: iso-8859-1 -*-
      2
      3  """Provides scanning patterns to be used as building blocks for more complex
      4  scans.
      5
      6  Strategies are different ways in which target scans may be done. We provide
      7  basic functionality so more complex stuff can be built upon this.
      8  """
      9
     10  # Copyright (C) 2004, 2005, 2006, 2010  Juan M. Bello Rivas <jmbr@superadditive.com>
     11  #
     12  # This program is free software; you can redistribute it and/or modify
     13  # it under the terms of the GNU General Public License as published by
     14  # the Free Software Foundation; either version 2 of the License, or
     15  # (at your option) any later version.
     16  #
     17  # This program is distributed in the hope that it will be useful,
     18  # but WITHOUT ANY WARRANTY; without even the implied warranty of
     19  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     20  # GNU General Public License for more details.
     21  #
     22  # You should have received a copy of the GNU General Public License
     23  # along with this program; if not, write to the Free Software
     24  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     25
     26
     27  import Halberd.crew
     28  import Halberd.logger
     29  import Halberd.reportlib
     30  import Halberd.clues.file
     31  import Halberd.clues.analysis as analysis
     32
     33
     34 -class ScanError(Exception):
     35      """Generic error during scanning.
     36      """
     37 -    def __init__(self, msg):
     38          self.msg = msg
     39
     40 -    def __str__(self):
     41          return str(self.msg)
     42
     43
     44 -class BaseStrategy:
     45      """Defines the strategy used to scan.
     46
     47      A strategy is a certain way to use the program. Theses can be layered to
     48      build a bigger strategy doing more complex things, etc.
     49      """
     50 -    def __init__(self, scantask):
     51          self.task = scantask
     52          self.logger = Halberd.logger.getLogger()
     53
     54 -    def execute(self):
     55          """Executes the strategy.
     56          """
     57          pass
     58
     59      # ---------------------------
     60      # Higher-level helper methods
     61      # ---------------------------
     62
     63 -    def _scan(self):
     64          """Allocates a work crew of scanners and launches them on the target.
     65          """
     66          assert self.task.url and self.task.addr
     67
     68          self.task.clues = []
     69          self.task.analyzed = []
     70          crew = Halberd.crew.WorkCrew(self.task)
     71          self.task.clues = crew.scan()
     72
     73 -    def _analyze(self):
     74          """Performs clue analysis.
     75          """
     76          if len(self.task.clues) == 0:
     77              return
     78
     79          self.task.analyzed = analysis.analyze(self.task.clues)
     80          self.task.analyzed = analysis.reanalyze(self.task.clues,
     81                                  self.task.analyzed, self.task.ratio_threshold)
     82
     83 -class UniScanStrategy(BaseStrategy):
     84      """Scan a single URL.
     85      """
     86 -    def __init__(self, scantask):
     87          BaseStrategy.__init__(self, scantask)
     88
     89          if not self.task.url:
     90              raise ScanError, 'Didn\'t provide an URL to scan'
     91
     92          if self.task.addr:
     93              # The user passed a specific address as a parameter.
     94              self.addrs = [self.task.addr]
     95          else:
     96              host = Halberd.util.hostname(self.task.url)
     97              self.logger.info('looking up host %s... ', host)
     98
     99              try:
    100                  self.addrs = Halberd.util.addresses(host)
    101              except KeyboardInterrupt:
    102                  raise ScanError, 'interrupted by the user'
    103
    104              if not self.addrs:
    105                  raise ScanError, 'unable to resolve %s' % host
    106
    107              self.addrs.sort()
    108              self.logger.info('host lookup done.')
    109
    110              if len(self.addrs) > 1:
    111                  for addr in self.addrs:
    112                      #self.logger.debug('%s resolves to %s', host, addr)
    113                      self.logger.info('%s resolves to %s', host, addr)
    114
    115 -    def execute(self):
    116          """Scans, analyzes and presents results coming a single target.
    117          """
    118          if self.task.save:
    119              cluedir = Halberd.clues.file.ClueDir(self.task.save)
    120
    121          for self.task.addr in self.addrs:
    122              self._scan()
    123
    124              self._analyze()
    125              Halberd.reportlib.report(self.task)
    126
    127              if self.task.save:
    128                  cluedir.save(self.task.url,
    129                               self.task.addr,
    130                               self.task.clues)
    131
    132 -class MultiScanStrategy(BaseStrategy):
    133      """Scan multiple URLs.
    134      """
    135 -    def __init__(self, scantask):
    136          BaseStrategy.__init__(self, scantask)
    137
    138          if not self.task.urlfile:
    139              raise ScanError, 'An urlfile parameter must be provided'
    140
    141          self.urlfp = open(self.task.urlfile, 'r')
    142
    143 -    def _targets(self, urlfp):
    144          """Obtain target addresses from URLs.
    145
    146          @param urlfp: File where the list of URLs is stored.
    147          @type urlfp: C{file}
    148
    149          @return: Generator providing the desired addresses.
    150          """
    151          for url in urlfp:
    152              if url == '\n':
    153                  continue
    154
    155              # Strip end of line character and whitespaces.
    156              url = url[:-1].strip()
    157
    158              host = Halberd.util.hostname(url)
    159              if not host:
    160                  self.logger.warn('unable to extract hostname from %s', host)
    161                  continue
    162
    163              self.logger.info('looking up host %s... ', host)
    164              try:
    165                  addrs = Halberd.util.addresses(host)
    166              except KeyboardInterrupt:
    167                  raise ScanError, 'interrupted by the user'
    168              self.logger.info('host lookup done.')
    169
    170              for addr in addrs:
    171                  yield (url, addr)
    172
    173 -    def execute(self):
    174          """Launch a multiple URL scan.
    175          """
    176          cluedir = Halberd.clues.file.ClueDir(self.task.save)
    177
    178          for url, addr in self._targets(self.urlfp):
    179              self.task.url = url
    180              self.task.addr = addr
    181              self.logger.info('scanning %s (%s)', url, addr)
    182              self._scan()
    183
    184              cluedir.save(url, addr, self.task.clues)
    185
    186              self._analyze()
    187
    188              Halberd.reportlib.report(self.task)
    189
    190 -class ClueReaderStrategy(BaseStrategy):
    191      """Clue reader strategy.
    192
    193      Works by reading and analyzing files of previously stored clues.
    194      """
    195 -    def __init__(self, scantask):
    196          BaseStrategy.__init__(self, scantask)
    197
    198 -    def execute(self):
    199          """Reads and interprets clues.
    200          """
    201          self.task.clues = Halberd.clues.file.load(self.task.cluefile)
    202          self._analyze()
    203          self.task.url = self.task.cluefile
    204          Halberd.reportlib.report(self.task)
    205
    206
    207  # vim: ts=4 sw=4 et
    208