Initial sendkeys support - warvox - VoIP based wardialing tool, forked from rapid7/warvox.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit 07cd8ffe0f62330affa86200ede6ba5b3c429fac
 (DIR) parent 48debf5ff874498ac73db2273708fcd65ebe90dc
 (HTM) Author: HD Moore <x@hdm.io>
       Date:   Sun, 28 Feb 2016 22:16:00 -0600
       
       Initial sendkeys support
       
       Diffstat:
         M lib/warvox/proto/iax2/client.rb     |      71 +++++++++++++++++++++++--------
       
       1 file changed, 54 insertions(+), 17 deletions(-)
       ---
 (DIR) diff --git a/lib/warvox/proto/iax2/client.rb b/lib/warvox/proto/iax2/client.rb
       @@ -14,8 +14,8 @@ module IAX2
        class Client
        
          attr_accessor :caller_number, :caller_name, :server_host, :server_port
       -  attr_accessor :username, :password
       -  attr_accessor :sock, :monitor
       +  attr_accessor :username, :password, :sendkeys
       +  attr_accessor :sock, :monitor_thread, :sendkeys_thread, :mutex
          attr_accessor :src_call_idx
          attr_accessor :debugging
          attr_accessor :calls
       @@ -36,21 +36,27 @@ class Client
            self.password      = opts[:password]
            self.debugging     = opts[:debugging]
        
       +    if opts[:sendkeys]
       +      self.sendkeys = opts[:sendkeys].unpack("C*").pack("C*")
       +    end
       +
            self.sock = Rex::Socket::Udp.create(
              'PeerHost' => self.server_host,
              'PeerPort' => self.server_port,
              'Context'  => opts[:context]
            )
        
       -    self.monitor   = ::Thread.new { monitor_socket }
       -
       +    self.monitor_thread = ::Thread.new { monitor_socket }
       +    self.mutex = ::Mutex.new
            self.src_call_idx = 0
            self.calls = {}
       -
          end
        
          def shutdown
       -    self.monitor.kill rescue nil
       +    self.monitor_thread.kill rescue nil
       +    if self.sendkeys_thread
       +      self.sendkeys_thread.kill rescue nil
       +    end
          end
        
          def create_call
       @@ -73,7 +79,14 @@ class Client
                next if not mcall
        
                if (pkt[0,1].unpack("C")[0] & 0x80) != 0
       +          prestate = mcall.state
                  mcall.handle_control(pkt)
       +
       +          # Start the sendkeys thread when the call is answered
       +          if mcall.state != prestate && mcall.state == :answered &&
       +             self.sendkeys && ! self.sendkeys_thread
       +            self.sendkeys_thread = Thread.new { sendkeys_runner(mcall) }
       +          end
                else
                  # Dispatch the buffer via the call handler
                  mcall.handle_audio(pkt)
       @@ -87,6 +100,7 @@ class Client
          end
        
          def matching_call(pkt)
       +    return unless pkt && pkt.length > 4
            src_call = pkt[0,2].unpack('n')[0]
            dst_call = nil
        
       @@ -106,13 +120,30 @@ class Client
            mcall
          end
        
       -  def allocate_call_id
       -    res = ( self.src_call_idx += 1 )
       -    if ( res > 0x8000 )
       -      self.src_call_idx = 1
       -      res = 1
       +  def sendkeys_runner(call)
       +    begin
       +    self.sendkeys.each_char do |c|
       +      case c
       +      when ','
       +        dprint("#{Thread.current} Sleeping 1s...")
       +        sleep(1.0)
       +      when /^[0-9#]$/
       +        dprint("#{Thread.current} Sending key #{c}")
       +        send_dtmf(call, c, :begin)
       +        sleep(0.3)
       +        send_dtmf(call, c, :end)
       +        sleep(0.3)
       +      else
       +        dprint("#{Thread.current} Unknown sendkey parameter: #{c}")
       +      end
            end
       -    res
       +  rescue ::Exception => e
       +    dprint("Error in sendkeys: #{e.class} #{e} #{e.backtrace}")
       +  end
       +  end
       +
       +  def allocate_call_id
       +    (self.src_call_idx += 1) & 0x7fff
          end
        
          def dprint(msg)
       @@ -121,11 +152,13 @@ class Client
          end
        
          def send_data(call, data, inc_seq = true )
       -    r = self.sock.sendto(data, self.server_host, self.server_port, 0)
       -    if inc_seq
       -      call.oseq = (call.oseq + 1) & 0xff
       +    self.mutex.synchronize do
       +      r = self.sock.sendto(data, self.server_host, self.server_port, 0)
       +      if inc_seq
       +        call.oseq = (call.oseq + 1) & 0xff
       +      end
       +      r
            end
       -    r
          end
        
          def send_ack(call)
       @@ -159,6 +192,11 @@ class Client
            send_data( call, create_pkt( call.scall, call.dcall, call.timestamp, call.oseq, call.iseq, IAX_TYPE_VOICE, data ) )
          end
        
       +  def send_dtmf(call, code, action)
       +    itype = (action == :begin) ? IAX_TYPE_DTMF_BEGIN : IAX_TYPE_DTMF_END
       +    send_data( call, create_pkt( call.scall, call.dcall, call.timestamp, call.oseq, call.iseq, itype, code ) )
       +  end
       +
          def send_new(call, number)
            data = [ IAX_SUBTYPE_NEW ].pack('C')
        
       @@ -227,4 +265,3 @@ end
        end
        end
        end
       -