| dun dun dun - warvox - VoIP based wardialing tool, forked from rapid7/warvox. | |
| Log | |
| Files | |
| Refs | |
| README | |
| --- | |
| commit e74d9b6a4be8bdbcb582358098f62a3743e772ce | |
| parent d05b856011c786fc8dee983a873228607ff7a9a0 | |
| Author: HD Moore <[email protected]> | |
| Date: Wed, 3 Aug 2011 22:42:01 +0000 | |
| dun dun dun | |
| Diffstat: | |
| M Makefile | 13 +++---------- | |
| M etc/warvox.conf | 2 +- | |
| M lib/warvox.rb | 2 +- | |
| D src/iaxrecord/Makefile | 4 ---- | |
| D src/iaxrecord/iaxrecord.c | 310 -----------------------------… | |
| M web/Gemfile | 3 +-- | |
| M web/Gemfile.lock | 2 ++ | |
| M web/app/controllers/analyze_contro… | 70 +++++++++++++++------------… | |
| M web/config/database.yml | 30 +++++++++--------------------- | |
| M web/config/environments/production… | 3 ++- | |
| 10 files changed, 53 insertions(+), 386 deletions(-) | |
| --- | |
| diff --git a/Makefile b/Makefile | |
| @@ -3,16 +3,12 @@ all: test | |
| test: install | |
| bin/verify_install.rb | |
| -install: bundler iaxrecord dtmf2num ruby-kissfft db | |
| - cp -a src/iaxrecord/iaxrecord bin/ | |
| +install: bundler dtmf2num ruby-kissfft db | |
| cp -a src/dtmf2num/dtmf2num bin/ | |
| ruby-kissfft-install: ruby-kissfft | |
| cp -a src/ruby-kissfft/kissfft.so lib/ | |
| -iaxrecord: | |
| - make -C src/iaxrecord/ | |
| - | |
| dtmf2num: | |
| make -C src/dtmf2num/ | |
| @@ -20,10 +16,8 @@ ruby-kissfft: | |
| ( cd src/ruby-kissfft/; ruby extconf.rb ) | |
| make -C src/ruby-kissfft/ | |
| -db: web/db/production.sqlite3 | |
| +db: | |
| @echo "Checking the database.." | |
| - | |
| -web/db/production.sqlite3: ruby-kissfft-install | |
| (cd web; RAILS_ENV=production rake db:migrate ) | |
| bundler: | |
| @@ -39,6 +33,5 @@ bundler: | |
| clean: | |
| ( cd src/ruby-kissfft/; ruby extconf.rb ) | |
| make -C src/ruby-kissfft/ clean | |
| - make -C src/iaxrecord/ clean | |
| make -C src/dtmf2num/ clean | |
| - rm -f bin/iaxrecord lib/kissfft.so | |
| + rm -f lib/kissfft.so | |
| diff --git a/etc/warvox.conf b/etc/warvox.conf | |
| @@ -24,7 +24,7 @@ tools: | |
| gnuplot: gnuplot | |
| sox: sox | |
| lame: lame | |
| - iaxrecord: %BASE%/bin/iaxrecord | |
| + iaxrecord: %BASE%/bin/iaxrecord.rb | |
| dtmf2num: %BASE%/bin/dtmf2num | |
| # | |
| diff --git a/lib/warvox.rb b/lib/warvox.rb | |
| @@ -11,7 +11,7 @@ require 'warvox/db' | |
| # Global configuration | |
| module WarVOX | |
| - VERSION = '1.2.0' | |
| + VERSION = '1.9.9-dev' | |
| Base = File.expand_path(File.join(File.dirname(__FILE__), '..')) | |
| Conf = File.expand_path(File.join(Base, 'etc', 'warvox.conf')) | |
| JobManager = WarVOX::JobQueue.new | |
| diff --git a/src/iaxrecord/Makefile b/src/iaxrecord/Makefile | |
| @@ -1,4 +0,0 @@ | |
| -all: | |
| - gcc -Wall -o iaxrecord iaxrecord.c -liaxclient | |
| -clean: | |
| - rm -f iaxrecord *.o | |
| diff --git a/src/iaxrecord/iaxrecord.c b/src/iaxrecord/iaxrecord.c | |
| @@ -1,310 +0,0 @@ | |
| -/* | |
| - * IAXRecord: a utility for recording audio on an outbound IAX call | |
| - * | |
| - * Copyright (C) 2009-2010 Rapid7 LLC - H D Moore <hdm[at]metasploit.com> | |
| - * | |
| - * Based on simpleclient from the IAXClient distribution | |
| - * | |
| - * Copyright (C) 1999, Linux Support Services, Inc. | |
| - * | |
| - * Mark Spencer <[email protected]> | |
| - * | |
| - * This program is free software, distributed under the terms of | |
| - * the GNU General Public License | |
| - */ | |
| - | |
| -#define TEST_MODE 1 | |
| - | |
| -#include <stdio.h> | |
| -#include <stdlib.h> | |
| -#include <unistd.h> | |
| -#include <sys/stat.h> | |
| -#include <fcntl.h> | |
| -#include <time.h> | |
| -#include <signal.h> | |
| - | |
| -#include <iaxclient.h> | |
| - | |
| -int initialized = 0; | |
| -int debug = 0; | |
| -int audio = 0; | |
| -int busy = 0; | |
| -int fail = 1; | |
| -int done = 0; | |
| - | |
| -float silence_threshold = 0.0f; | |
| -int call_state = 0; | |
| -int call_trace = -1; | |
| -int call_done = 0; | |
| -int call_bytes = 0; | |
| -char *iax_out; | |
| -int reg_id; | |
| - | |
| -#ifdef TEST_MODE | |
| -int call_end = 0; | |
| -unsigned char empty_buf[200]; | |
| -#endif | |
| - | |
| -void signal_handler(int signum) { | |
| - if ( signum == SIGTERM || signum == SIGINT ) { | |
| - done = 1; | |
| - } | |
| -} | |
| - | |
| -void usage(char **argv) { | |
| - fprintf(stdout, "Usage: %s -s [server] -u [user] -p <pass> -o [output]… | |
| - exit(1); | |
| -} | |
| - | |
| -int state_event_callback(struct iaxc_ev_call_state call) { | |
| - if(call.state & IAXC_CALL_STATE_BUSY) busy = 1; | |
| - if(call.state & IAXC_CALL_STATE_COMPLETE) fail = 0; | |
| - | |
| - call_state = call.state; | |
| - | |
| - if(debug) { | |
| - fprintf(stdout, "STATE: "); | |
| - if(call.state & IAXC_CALL_STATE_FREE) | |
| - fprintf(stdout, "F"); | |
| - | |
| - if(call.state & IAXC_CALL_STATE_ACTIVE) | |
| - fprintf(stdout, "A"); | |
| - | |
| - if(call.state & IAXC_CALL_STATE_OUTGOING) | |
| - fprintf(stdout, "O"); | |
| - | |
| - if(call.state & IAXC_CALL_STATE_RINGING) | |
| - fprintf(stdout, "R"); | |
| - | |
| - if(call.state & IAXC_CALL_STATE_COMPLETE) | |
| - fprintf(stdout, "C"); | |
| - | |
| - if(call.state & IAXC_CALL_STATE_SELECTED) | |
| - fprintf(stdout, "S"); | |
| - | |
| - if(call.state & IAXC_CALL_STATE_BUSY) | |
| - fprintf(stdout, "B"); | |
| - | |
| - if(call.state & IAXC_CALL_STATE_TRANSFER) | |
| - fprintf(stdout, "T"); | |
| - | |
| - fprintf(stdout, "\n"); | |
| - fflush(stdout); | |
| - } | |
| - | |
| - return 0; | |
| -} | |
| - | |
| -int audio_event_callback( struct iaxc_ev_audio audio) { | |
| - | |
| - if(call_trace == -1 && !fail) { | |
| - call_trace = open(iax_out, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S… | |
| - } | |
| - | |
| - if(call_trace != -1) { | |
| - if(debug) printf("audio data: format=%d encoded=%d size=%d sta… | |
| - write(call_trace, audio.data, audio.size); | |
| - call_bytes += audio.size; | |
| - } | |
| - return 0; | |
| -} | |
| - | |
| -int iaxc_callback(iaxc_event e) { | |
| - switch(e.type) { | |
| - case IAXC_EVENT_TEXT: | |
| - // fprintf(stdout, "TEXT: %s\n", e.ev.text.message); | |
| - return ( debug ? 0 : 1 ); | |
| - break; | |
| - case IAXC_EVENT_STATE: | |
| - return state_event_callback(e.ev.call); | |
| - break; | |
| - case IAXC_EVENT_AUDIO: | |
| - return audio_event_callback(e.ev.audio); | |
| - break; | |
| - default: | |
| - return 0; | |
| - break; | |
| - } | |
| -} | |
| - | |
| - | |
| -int main(int argc, char **argv) { | |
| - | |
| - char *iax_host = NULL; | |
| - char *iax_user = NULL; | |
| - char *iax_pass = ""; | |
| - char *iax_num = NULL; | |
| - char *iax_cid = "15555555555"; | |
| - char *iax_name = ""; | |
| - int iax_sec = 20; | |
| - int call_id = 0; | |
| - char dest[1024]; | |
| - time_t stime, etime; | |
| - | |
| - int c; | |
| - extern char *optarg; | |
| - extern int optind, optopt; | |
| - | |
| - while ((c = getopt(argc, argv, ":hs:u:p:c:o:n:l:N:DA")) != -1) { | |
| - switch(c) { | |
| - case 'h': | |
| - usage(argv); | |
| - break; | |
| - case 's': | |
| - iax_host = optarg; | |
| - break; | |
| - case 'u': | |
| - iax_user = optarg; | |
| - break; | |
| - case 'p': | |
| - iax_pass = optarg; | |
| - break; | |
| - case 'c': | |
| - iax_cid = optarg; | |
| - break; | |
| - case 'o': | |
| - iax_out = optarg; | |
| - break; | |
| - case 'n': | |
| - iax_num = optarg; | |
| - break; | |
| - case 'l': | |
| - iax_sec = atoi(optarg); | |
| - break; | |
| - case 'N': | |
| - iax_name = optarg; | |
| - break; | |
| - case 'D': | |
| - debug = 1; | |
| - break; | |
| - case 'A': | |
| - audio = 1; | |
| - break; | |
| - } | |
| - } | |
| - | |
| - | |
| -/* | |
| - Version 2.2.x of iaxclient has a new function called iaxc_set_test_mode(1), … | |
| - audio processing for us. This will not be backported to 2.0.x however... | |
| -*/ | |
| - | |
| - if(! (iax_host && iax_user && iax_num && iax_out)) usage(argv); | |
| - | |
| - snprintf(dest, sizeof(dest), "%s:%s@%s/%s", iax_user, iax_pass, iax_ho… | |
| - iaxc_set_video_prefs(IAXC_VIDEO_PREF_CAPTURE_DISABLE | IAXC_VIDEO_PREF… | |
| - iaxc_set_audio_prefs(IAXC_AUDIO_PREF_SEND_DISABLE); | |
| - | |
| - if(! debug) { | |
| - fclose(stderr); | |
| - stderr = fopen("/dev/null", "w"); | |
| - } | |
| - | |
| - fprintf(stdout, "STARTED %s BYTES=%d FILE=%s\n", iax_num, call_bytes, … | |
| - | |
| - /* install signal handler to catch CRTL-Cs */ | |
| - signal(SIGINT, signal_handler); | |
| - signal(SIGTERM, signal_handler); | |
| - | |
| - /* enable test mode */ | |
| -#ifdef TEST_MODE | |
| - iaxc_set_test_mode(1); | |
| -#endif | |
| - | |
| - /* forcible disable pulse audio if the audio flag is not set (-A) */ | |
| - // if(! audio) setenv("PULSE_SERVER", "255.255.255.255", 1); | |
| - | |
| - setenv("ALSA_PCM_CARD", "pcm.null", 1); | |
| - setenv("ALSA_CARD", "pcm.null", 1); | |
| - setenv("ALSA_DEVICE", "pcm.null", 1); | |
| - | |
| - if(debug) fprintf(stderr, ">> INITIALIZING\n"); | |
| - if ( iaxc_initialize(1) ) { | |
| - fprintf(stdout, "error: Could not initialize iaxclient!\n"); | |
| - exit(0); | |
| - } | |
| - | |
| - initialized = 1; | |
| - if(debug) fprintf(stderr, ">> INITIALIZED\n"); | |
| - | |
| - iaxc_set_audio_output(audio ? 0 : 1); | |
| - iaxc_set_callerid (iax_name, iax_cid); | |
| - iaxc_set_formats(IAXC_FORMAT_ULAW | IAXC_FORMAT_ALAW, IAXC_FORMAT_ULAW… | |
| - | |
| - // Causes problems for some asterix servers, not sure why yet | |
| - // iaxc_set_silence_threshold(silence_threshold); | |
| - | |
| - if(debug) fprintf(stderr, ">> STARTING PROCESSING THREAD\n"); | |
| - iaxc_set_event_callback(iaxc_callback); | |
| - iaxc_start_processing_thread(); | |
| - if(debug) fprintf(stderr, ">> STARTED PROCESSING THREAD\n"); | |
| - | |
| - iaxc_set_audio_prefs(IAXC_AUDIO_PREF_RECV_REMOTE_RAW); | |
| - | |
| - if(debug) fprintf(stderr, ">> REGISTERING\n") ; | |
| - reg_id = iaxc_register(iax_user, iax_pass, iax_host); | |
| - if(debug) fprintf(stderr, ">> REGISTERED: %d\n", reg_id); | |
| - | |
| - if(debug) fprintf(stderr, ">> CALLING\n"); | |
| - call_id = iaxc_call(dest); | |
| - if(debug) fprintf(stderr, ">> CALLED: %d\n", call_id); | |
| - | |
| - stime = time(NULL); | |
| - etime = 0; | |
| - | |
| - if(debug) fprintf(stderr, ">> WAITING\n"); | |
| - if(call_id >= 0) { | |
| - iaxc_select_call(call_id); | |
| - while((unsigned int)(time(NULL))-(unsigned int)stime < iax_sec… | |
| - if(done) break; | |
| - if(call_state & IAXC_CALL_STATE_COMPLETE && ! etime) e… | |
| - if(call_state & IAXC_CALL_STATE_BUSY) break; | |
| - if(iaxc_first_free_call() == call_id) break; | |
| - iaxc_millisleep(250); | |
| - | |
| -#ifdef TEST_MODE | |
| - /* we need do send something to receive data... I don'… | |
| - if( !call_end && call_state & IAXC_CALL_STATE_COMPLETE… | |
| - iaxc_push_audio(&empty_buf[0], 200, 200); | |
| -#endif | |
| - | |
| - } | |
| - } else { | |
| - fail = 1; | |
| - } | |
| - | |
| - if(debug) fprintf(stderr, ">> DONE\n"); | |
| - | |
| - if(! etime) time(&etime); | |
| - | |
| - fprintf(stdout, "COMPLETED %s BYTES=%d FILE=%s FAIL=%d BUSY=%d RINGTIM… | |
| - iax_num, | |
| - call_bytes, | |
| - iax_out, | |
| - fail, | |
| - busy, | |
| - (unsigned int)(etime) - (unsigned int)(stime) | |
| - ); | |
| - | |
| - | |
| - iaxc_dump_call(); | |
| - iaxc_millisleep(500); | |
| - iaxc_stop_processing_thread(); | |
| - iaxc_shutdown(); | |
| - return(0); | |
| -} | |
| - | |
| -/* | |
| - | |
| -Note about ring times vs ring counts: | |
| - http://en.wikipedia.org/wiki/Ringtone#Ringing_signal | |
| - The ringing pattern is known as ring cadence. This only applies to POT… | |
| - the high voltage ring signal is switched on and off to create the ring… | |
| - America, the standard ring cadence is "2-4", or two seconds of ringing… | |
| - seconds of silence. In Australia and the UK, the standard ring cadence… | |
| - off, 400 ms on, 2000 ms off. These patterns may vary from region to re… | |
| - patterns are used in different countries around the world. | |
| - | |
| -ring count US = ringtime / 6.0 | |
| -ring count UK = ringtime / 3.0 | |
| -*/ | |
| diff --git a/web/Gemfile b/web/Gemfile | |
| @@ -5,8 +5,7 @@ gem 'rails', '3.0.1' | |
| # Bundle edge Rails instead: | |
| # gem 'rails', :git => 'git://github.com/rails/rails.git' | |
| -gem 'sqlite3-ruby', :require => 'sqlite3' | |
| - | |
| +gem 'pg', '0.11' | |
| # Use unicorn as the web server | |
| # gem 'unicorn' | |
| diff --git a/web/Gemfile.lock b/web/Gemfile.lock | |
| @@ -47,6 +47,7 @@ GEM | |
| mime-types (~> 1.16) | |
| treetop (~> 1.4.8) | |
| mime-types (1.16) | |
| + pg (0.11.0) | |
| polyglot (0.3.1) | |
| rack (1.2.1) | |
| rack-mount (0.6.13) | |
| @@ -77,6 +78,7 @@ PLATFORMS | |
| ruby | |
| DEPENDENCIES | |
| + pg (= 0.11) | |
| rails (= 3.0.1) | |
| sqlite3-ruby | |
| will_paginate! | |
| diff --git a/web/app/controllers/analyze_controller.rb b/web/app/controllers/an… | |
| @@ -1,9 +1,9 @@ | |
| class AnalyzeController < ApplicationController | |
| layout 'warvox' | |
| - | |
| + | |
| def index | |
| @jobs = DialJob.paginate( | |
| - :page => params[:page], | |
| + :page => params[:page], | |
| :order => 'id DESC', | |
| :per_page => 30 | |
| ) | |
| @@ -13,7 +13,7 @@ class AnalyzeController < ApplicationController | |
| @job_id = params[:id] | |
| @dial_job = DialJob.find(@job_id) | |
| @shown = params[:show] | |
| - | |
| + | |
| @g1 = Ezgraphix::Graphic.new(:c_type => 'col3d', :div_name => 'calls_p… | |
| @g1.render_options(:caption => 'Detected Lines by Type', :y_name => 'L… | |
| @@ -26,38 +26,38 @@ class AnalyzeController < ApplicationController | |
| :conditions => ['dial_job_id = ? and line_type = ?', @… | |
| ) | |
| end | |
| - | |
| + | |
| @g1.data = res_types | |
| if(@shown and @shown != 'all') | |
| @results = DialResult.where(:dial_job_id => @job_id).paginate( | |
| - :page => params[:page], | |
| + :page => params[:page], | |
| :order => 'number ASC', | |
| :per_page => 10, | |
| :conditions => [ 'completed = ? and processed = ? and … | |
| - ) | |
| + ) | |
| else | |
| @results = DialResult.where(:dial_job_id => @job_id).paginate( | |
| - :page => params[:page], | |
| + :page => params[:page], | |
| :order => 'number ASC', | |
| :per_page => 10, | |
| :conditions => [ 'completed = ? and processed = ? and … | |
| ) | |
| end | |
| - | |
| + | |
| @filters = [] | |
| @filters << { :scope => "all", :label => "All" } | |
| res_types.keys.each do |t| | |
| @filters << { :scope => t.to_s.downcase, :label => t.to_s } | |
| end | |
| - | |
| + | |
| end | |
| def show | |
| @job_id = params[:id] | |
| @dial_job = DialJob.find(@job_id) | |
| @shown = params[:show] | |
| - | |
| + | |
| @g1 = Ezgraphix::Graphic.new(:c_type => 'col3d', :div_name => 'calls_p… | |
| @g1.render_options(:caption => 'Detected Lines by Type', :y_name => 'L… | |
| @@ -70,31 +70,31 @@ class AnalyzeController < ApplicationController | |
| :conditions => ['dial_job_id = ? and line_type = ?', @… | |
| ) | |
| end | |
| - | |
| + | |
| @g1.data = res_types | |
| if(@shown and @shown != 'all') | |
| @results = DialJob.where(:id => @job_id).paginate( | |
| - :page => params[:page], | |
| + :page => params[:page], | |
| :order => 'number ASC', | |
| :per_page => 20, | |
| :conditions => [ 'completed = ? and processed = ? and … | |
| - ) | |
| + ) | |
| else | |
| @results = DialJob.where(:id => @job_id).paginate( | |
| - :page => params[:page], | |
| + :page => params[:page], | |
| :order => 'number ASC', | |
| :per_page => 20, | |
| :conditions => [ 'completed = ? and processed = ? and … | |
| ) | |
| end | |
| - | |
| + | |
| @filters = [] | |
| @filters << { :scope => "all", :label => "All" } | |
| res_types.keys.each do |t| | |
| @filters << { :scope => t.to_s.downcase, :label => t.to_s } | |
| end | |
| - | |
| + | |
| end | |
| @@ -102,42 +102,40 @@ class AnalyzeController < ApplicationController | |
| def resource | |
| ctype = 'text/html' | |
| cpath = nil | |
| - | |
| + cdata = "File not found" | |
| + | |
| res = DialResult.find(params[:result_id]) | |
| - if(res and res.processed and res.rawfile) | |
| + | |
| + if res | |
| case params[:type] | |
| when 'big_sig' | |
| ctype = 'image/png' | |
| - cpath = res.rawfile.gsub(/\..*/, '') + '_big.png' | |
| + cdata = res.png_sig_freq | |
| when 'big_sig_dots' | |
| ctype = 'image/png' | |
| - cpath = res.rawfile.gsub(/\..*/, '') + '_big_dots.png'… | |
| + cdata = res.png_big_dots | |
| when 'small_sig' | |
| ctype = 'image/png' | |
| - cpath = res.rawfile.gsub(/\..*/, '') + '.png' | |
| + cdata = res.png_sig | |
| + when 'big_freq' | |
| + ctype = 'image/png' | |
| + cdata = res.png_big_freq | |
| + when 'small_freq' | |
| + ctype = 'image/png' | |
| + cdata = res.png_sig_freq | |
| when 'mp3' | |
| ctype = 'audio/mpeg' | |
| - cpath = res.rawfile.gsub(/\..*/, '') + '.mp3' | |
| + cdata = res.mp3 | |
| when 'sig' | |
| ctype = 'text/plain' | |
| - cpath = res.rawfile.gsub(/\..*/, '') + '.sig' | |
| + cdata = res.fprint | |
| when 'raw' | |
| ctype = 'octet/binary-stream' | |
| - cpath = res.rawfile | |
| - when 'big_freq' | |
| - ctype = 'image/png' | |
| - cpath = res.rawfile.gsub(/\..*/, '') + '_freq_big.png'… | |
| - when 'small_freq' | |
| - ctype = 'image/png' | |
| - cpath = res.rawfile.gsub(/\..*/, '') + '_freq.png' … | |
| + cdata = res.audio | |
| end | |
| end | |
| - | |
| - cdata = "File not found" | |
| - if(cpath and File.readable?(cpath)) | |
| - cdata = File.read(cpath, File.size(cpath)) | |
| - end | |
| - | |
| + | |
| send_data(cdata, :type => ctype, :disposition => 'inline') | |
| end | |
| end | |
| + | |
| diff --git a/web/config/database.yml b/web/config/database.yml | |
| @@ -1,22 +1,10 @@ | |
| -# SQLite version 3.x | |
| -# gem install sqlite3-ruby (not necessary on OS X Leopard) | |
| -development: | |
| - adapter: sqlite3 | |
| - database: db/development.sqlite3 | |
| - pool: 5 | |
| - timeout: 5000 | |
| - | |
| -# Warning: The database defined as "test" will be erased and | |
| -# re-generated from your development database when you run "rake". | |
| -# Do not set this db to the same as development or production. | |
| -test: | |
| - adapter: sqlite3 | |
| - database: db/test.sqlite3 | |
| - pool: 5 | |
| - timeout: 5000 | |
| - | |
| production: | |
| - adapter: sqlite3 | |
| - database: db/production.sqlite3 | |
| - pool: 5 | |
| - timeout: 5000 | |
| + adapter: postgresql | |
| + database: warvox | |
| + username: warvox | |
| + password: "<yourpass>" | |
| + host: 127.0.0.1 | |
| + port: 5433 | |
| + pool: 100 | |
| + timeout: 5 | |
| + | |
| diff --git a/web/config/environments/production.rb b/web/config/environments/pr… | |
| @@ -6,7 +6,7 @@ Web::Application.configure do | |
| config.cache_classes = true | |
| # Full error reports are disabled and caching is turned on | |
| - config.consider_all_requests_local = true | |
| + config.consider_all_requests_local = false | |
| config.action_controller.perform_caching = true | |
| # Specifies the header that your server uses for sending files | |
| @@ -47,3 +47,4 @@ Web::Application.configure do | |
| # Send deprecation notices to registered listeners | |
| config.active_support.deprecation = :notify | |
| end | |
| + |