URI: 
       See changelog - warvox - VoIP based wardialing tool, forked from rapid7/warvox.
   DIR Log
   DIR Files
   DIR Refs
   DIR README
       ---
   DIR commit 24678be5de812202bd8b96babaac256a95bb668f
   DIR parent e60cddbfb6b561a97734e9e6a9c82dad885bb8de
  HTML Author: HD Moore <hd_moore@rapid7.com>
       Date:   Mon, 11 May 2009 03:41:22 +0000
       
       See changelog
       
       
       Diffstat:
         M docs/BUGS                           |       4 +++-
         M docs/ChangeLog                      |      10 +++++++++-
         A etc/blacklist.txt                   |      11 +++++++++++
         M etc/warvox.conf                     |       7 ++++++-
         M lib/warvox.rb                       |       2 +-
         M lib/warvox/config.rb                |      26 ++++++++++++++++++++++++++
         M lib/warvox/jobs/dialer.rb           |      12 ++++++++++++
         M lib/warvox/phone.rb                 |      13 ++++++++++---
         M web/app/controllers/dial_jobs_cont… |      14 +++++++++-----
         M web/app/models/dial_job.rb          |       4 +++-
         M web/app/views/dial_jobs/index.html… |      17 +++++++++++++----
         M web/app/views/dial_jobs/new.html.e… |      15 ++++++++++++---
         M web/app/views/home/about.html.erb   |      17 +++++++++++++----
         M web/public/stylesheets/global.css   |      12 ++++++++++++
       
       14 files changed, 140 insertions(+), 24 deletions(-)
       ---
   DIR diff --git a/docs/BUGS b/docs/BUGS
       @@ -3,4 +3,6 @@ KNOWN BUGS
         * Stopping WarVOX in mid-scan will leave a hung scan job, the job will
           need to be removed and restarted.
         
       - 
       + * Using the sound card (playing music, videos, etc) while warvox is running
       +   can cause the dialing process to handle. Systems without sound cards are
       +   not affected.
   DIR diff --git a/docs/ChangeLog b/docs/ChangeLog
       @@ -1,4 +1,12 @@
       +2009-05-10  H D Moore  <hdm[at]metasploit.com>
       + 
       + * release of version 1.0.1
       + * switched to the BSD license for WarVOX
       + * swapped the sox -w flag to -2 (deprecated)
       + * added support for multiple dial masks for a single job
       + * added support for number exclusions (blacklists)
       + * added support for file input for a dial range
       + 
        2009-03-05  H D Moore  <hdm[at]metasploit.com>
        
         * initial public release of version 1.0.0
       -
   DIR diff --git a/etc/blacklist.txt b/etc/blacklist.txt
       @@ -0,0 +1,11 @@
       +#
       +# Fill this with a list of regular expressions to match all
       +# dialed numbers against. No number matching an entry in this
       +# file should ever be dialed.
       +#
       +
       +# Never dial just zero
       +^0$
       +
       +# Skip all of the [X]11 numbers, such as 911, 411, and 111
       +^[0-9]11$
   DIR diff --git a/etc/warvox.conf b/etc/warvox.conf
       @@ -13,7 +13,7 @@ authentication:
        
        #
        # Configure the path to all saved data files
       -# This requires ~500M of space per prefix
       +# This requires ~500M of space per 10k prefix
        #
        data_path: %BASE%/data/
        
       @@ -33,3 +33,8 @@ tools:
        # value is twice your core count.
        #
        analysis_threads: 2
       +
       +#
       +# Configure the dial blacklist location
       +#
       +blacklist: %BASE%/etc/blacklist.txt
   DIR diff --git a/lib/warvox.rb b/lib/warvox.rb
       @@ -11,7 +11,7 @@ require 'warvox/db'
        
        # Global configuration
        module WarVOX
       -        VERSION = '1.0.0'
       +        VERSION = '1.0.1'
                Base = File.expand_path(File.join(File.dirname(__FILE__), '..'))
                Conf = File.expand_path(File.join(Base, 'etc', 'warvox.conf'))
                JobManager = WarVOX::JobQueue.new
   DIR diff --git a/lib/warvox/config.rb b/lib/warvox/config.rb
       @@ -45,7 +45,33 @@ module Config
                        return 1 if not info['analysis_threads']
                        [ info['analysis_threads'].to_i, 1 ].max
                end
       +        
       +        def self.blacklist_path
       +                info = YAML.load_file(WarVOX::Conf)
       +                return nil if not info
       +                return nil if not info['blacklist']
       +                File.expand_path(info['blacklist'].gsub('%BASE%', WarVOX::Base))
       +        end
        
       +        def self.blacklist_load
       +                path = blacklist_path
       +                return if not path
       +                data = File.read(path, File.size(path))
       +                sigs = []
       +                
       +                File.open(path, 'r') do |fd|
       +                        lno = 0
       +                        fd.each_line do |line|
       +                                lno += 1
       +                                next if line =~ /^#/
       +                                next if line =~ /^\s+$/
       +                                line.strip!
       +                                sigs << [lno, line]
       +                        end
       +                        sigs
       +                end
       +                
       +        end
        
                # This method searches the PATH environment variable for
                # a fully qualified path to the supplied file name.
   DIR diff --git a/lib/warvox/jobs/dialer.rb b/lib/warvox/jobs/dialer.rb
       @@ -93,6 +93,18 @@ class Dialer < Base
                        dest = File.join(WarVOX::Config.data_path, "#{@name}")
                        FileUtils.mkdir_p(dest)
                
       +                # Scrub all numbers matching the blacklist
       +                list = WarVOX::Config.blacklist_load
       +                list.each do |b|
       +                        lno,reg = b
       +                        @nums.each do |num|
       +                                if(num =~ /#{reg}/)
       +                                        $stderr.puts "DEBUG: Skipping #{num} due to blacklist (line: #{lno})"
       +                                        @nums.delete(num)
       +                                end
       +                        end
       +                end
       +        
                        @nums_total = @nums.length
                        while(@nums.length > 0)
                                @calls    = []
   DIR diff --git a/lib/warvox/phone.rb b/lib/warvox/phone.rb
       @@ -6,6 +6,16 @@ class Phone
                        res = {}
                        masks.each do |mask|
                                mask = mask.strip
       +                        
       +                        if(mask.index(':'))
       +                                next if mask.index('X')
       +                                rbeg,rend = mask.split(':').map{|c| c.gsub(/[^\d]/, '').to_i }
       +                                rbeg.upto(rend) do |n|
       +                                        res[n.to_s] = {}
       +                                end
       +                                next
       +                        end
       +                        
                                incdigits = 0
                                mask.each_char do |c|
                                        incdigits += 1 if c =~ /^[X#]$/i
       @@ -27,9 +37,6 @@ class Phone
                                end
                
                        end
       -                res.each { |key, value|
       -                        print "DEBUG: key=",key," -> ",value,"\n"
       -                }
        
                        return res.keys.sort
                end
   DIR diff --git a/web/app/controllers/dial_jobs_controller.rb b/web/app/controllers/dial_jobs_controller.rb
       @@ -5,7 +5,7 @@ class DialJobsController < ApplicationController
          # GET /dial_jobs.xml
          def index
                  @submitted_jobs = DialJob.find_all_by_status('submitted')
       -    @active_jobs    = DialJob.find_all_by_status('active')
       +        @active_jobs    = DialJob.find_all_by_status('active')
                @new_job        = DialJob.new
            respond_to do |format|
              format.html # index.html.erb
       @@ -43,7 +43,7 @@ class DialJobsController < ApplicationController
          
          def stop
            @dial_job = DialJob.find(params[:id])
       -        
       +
                if(@dial_job.status != 'submitted')
                  flash[:notice] = 'Job is already running or completed'
                  return
       @@ -54,11 +54,11 @@ class DialJobsController < ApplicationController
          # POST /dial_jobs
          # POST /dial_jobs.xml
          def create
       -          
       +                                   
                @dial_job = DialJob.new(params[:dial_job])
          
            if(Provider.find_all_by_enabled(true).length == 0)
       -                @dial_job.errors.add("No providers have been configured or enabled, this job ")
       +                @dial_job.errors.add("No providers have been configured or enabled, this job cannot be run")
                        respond_to do |format|
                                format.html { render :action => "new" }
                                format.xml  { render :xml => @dial_job.errors, :status => :unprocessable_entity }
       @@ -70,9 +70,13 @@ class DialJobsController < ApplicationController
                @dial_job.progress     = 0
                @dial_job.started_at   = nil
                @dial_job.completed_at = nil
       -        @dial_job.range.gsub!(/[^0-9X,\n]/, '')
       +        @dial_job.range.gsub!(/[^0-9X:,\n]/, '')
                @dial_job.cid_mask.gsub!(/[^0-9X]/, '') if @dial_job.cid_mask != "SELF"
        
       +        if(@dial_job.range_file.to_s != "")
       +                @dial_job.range = @dial_job.range_file.read.gsub!(/[^0-9X:,\n]/, '')
       +        end
       +
            respond_to do |format|
              if @dial_job.save
                flash[:notice] = 'Job was successfully created.'
   DIR diff --git a/web/app/models/dial_job.rb b/web/app/models/dial_job.rb
       @@ -1,4 +1,6 @@
        class DialJob < ActiveRecord::Base
       +        attr_accessor :range_file
       +        
                has_many :dial_results
        
                validates_presence_of :range, :lines, :seconds
       @@ -6,7 +8,7 @@ class DialJob < ActiveRecord::Base
                validates_numericality_of :seconds, :less_than => 301, :greater_than => 0
        
                def validate
       -                if(range.gsub(/[^0-9X,\n]/, '').empty?)
       +                if(range.gsub(/[^0-9X:,\n]/, '').empty?)
                                errors.add(:range, "The range must be at least 1 character long and made up of 0-9 and X as the mask.")
                        end
                        
   DIR diff --git a/web/app/views/dial_jobs/index.html.erb b/web/app/views/dial_jobs/index.html.erb
       @@ -74,24 +74,33 @@
        <% end %>
        <h1 class='title'>Submit a New Job</h1>
        
       -<% form_for(@new_job) do |f| %>
       +<% form_for(@new_job, :html => { :multipart => true }) do |f| %>
          <%= f.error_messages %>
          <p>
       -    <%= f.label :range, 'The target telephone range (1-123-456-XXXX)' %><br />
       +    <%= f.label :range, 'Specify target telephone range(s) (1-123-456-7890 or 1-123-456-XXXX or 1-123-300-1000:1-123-400-2000)' %><br />
            <%= f.text_area :range, :size => "35x5" %>
          </p>
       +  
       +  <p>
       +    <%= f.label :range_file, 'Or upload a file containing the target ranges' %><br />
       +    <%= f.file_field :range_file %>
       +  </p>
       +  
          <p>
            <%= f.label :seconds, 'Seconds of audio to capture' %><br />
            <%= f.text_field :seconds, :value => 53 %>
          </p>
       +  
          <p>
            <%= f.label :lines, 'Maximum number of outgoing lines' %><br />
            <%= f.text_field :lines, :value => 10 %>
          </p>
       +  
          <p>
       -    <%= f.label :lines, 'The source Caller ID range (1-555-555-55XX)' %><br />
       +    <%= f.label :lines, 'The source Caller ID range (1-555-555-5555 or 1-555-555-55XX)' %><br />
            <%= f.text_field :cid_mask, :value => '1-123-456-XXXX' %>
       -  </p>  
       +  </p>
       +  
          <p>
            <%= f.submit "Create" %>
          </p>
   DIR diff --git a/web/app/views/dial_jobs/new.html.erb b/web/app/views/dial_jobs/new.html.erb
       @@ -1,23 +1,32 @@
        <h1 class='title'>Submit a New Job</h1>
        
       -<% form_for(@dial_job) do |f| %>
       +<% form_for(@dial_job, :html => { :multipart => true }) do |f| %>
          <%= f.error_messages %>
          <p>
       -    <%= f.label :range, 'The target telephone range (1-123-456-XXXX)' %><br />
       +    <%= f.label :range, 'Specify target telephone range(s) (1-123-456-7890 or 1-123-456-XXXX or 1-123-300-1000:1-123-400-2000)' %><br />
            <%= f.text_area :range, :size => "35x5" %>
          </p>
       +  
       +  <p>
       +    <%= f.label :range_file, 'Or upload a file containing the target ranges' %><br />
       +    <%= f.file_field :range_file %>
       +  </p>
       +  
          <p>
            <%= f.label :seconds, 'Seconds of audio to capture' %><br />
            <%= f.text_field :seconds, :value => 53 %>
          </p>
       +  
          <p>
            <%= f.label :lines, 'Maximum number of outgoing lines' %><br />
            <%= f.text_field :lines, :value => 10 %>
          </p>
       +  
          <p>
            <%= f.label :lines, 'The source Caller ID range (1-555-555-55XX or SELF)' %><br />
            <%= f.text_field :cid_mask, :value => '1-123-456-XXXX' %>
       -  </p>  
       +  </p>
       +  
          <p>
            <%= f.submit "Create" %>
          </p>
   DIR diff --git a/web/app/views/home/about.html.erb b/web/app/views/home/about.html.erb
       @@ -4,10 +4,9 @@
        <h1 class='title'>About WarVOX</h1>
        
        <b>WarVOX</b> is a product of <a href="http://metasploit.com">Metasploit LLC</a> and is provided as 
       -free software under a 
       -<a href="http://creativecommons.org/licenses/by-nc/3.0/">non-commercial</a> license. WarVOX is 
       -intended for legal security assessment, asset inventory, and research purposes only. The latest version
       -of WarVOX can be found at <a href="http://warvox.org/">http://warvox.org/</a>. The WarVOX development
       +free software under the BSD license. WarVOX is intended for legal security assessment, asset inventory,
       +and research purposes only. The latest version of WarVOX can be found at
       +<a href="http://warvox.org/">http://warvox.org/</a>. The WarVOX development
        team can be reached by email at warvox[at]metasploit.com.
        
        </td><td valign='top' align='center'>
       @@ -129,5 +128,15 @@ team can be reached by email at warvox[at]metasploit.com.
        </tr>
        </table>
        
       +<br/><br/>
       +
       +<h1 class='title'>Dial Exclusions (Blacklist)</h1>
       +<table id="warvox_blacklist" cellspacing="0" width='100%'>
       +<tr>
       +        <td valign="top" align="left" class="header_item" width='200'>
       +                <pre><%=h File.read(WarVOX::Config.blacklist_path) %></pre>
       +        </td>
       +</tr>
       +</table>
        
        </td></tr></table>
   DIR diff --git a/web/public/stylesheets/global.css b/web/public/stylesheets/global.css
       @@ -134,6 +134,18 @@ h3 {
                padding: 0 10px 0px 6px;
        }
        
       +#warvox_blacklist {
       +        margin-top: 5px;
       +        border: 1px solid black;
       +        font-size: 12px;
       +        color: #555;
       +}
       +
       +#warvox_blacklist td {
       +        margin-left: 20px;
       +        padding: 0 10px 0px 6px;
       +}
       +
        #home_logo {
                border: 0;
        }