Class: Rex::Proto::DNS::Server::Cache

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/rex/proto/dns/server.rb

Constant Summary

Constants included from Constants

Constants::MATCH_HOSTNAME

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCache

class DNSRecordError < ::Exception

Create DNS Server cache


18
19
20
21
# File 'lib/rex/proto/dns/server.rb', line 18

def initialize
  @records = {}
  @lock = Mutex.new
end

Instance Attribute Details

#lockObject (readonly)

Returns the value of attribute lock


12
13
14
# File 'lib/rex/proto/dns/server.rb', line 12

def lock
  @lock
end

#monitor_threadObject (readonly)

Returns the value of attribute monitor_thread


12
13
14
# File 'lib/rex/proto/dns/server.rb', line 12

def monitor_thread
  @monitor_thread
end

#recordsObject (readonly)

Returns the value of attribute records


12
13
14
# File 'lib/rex/proto/dns/server.rb', line 12

def records
  @records
end

Instance Method Details

#add(record, expire = 0) ⇒ Object (protected)

Add a record to the cache with thread safety

Parameters:

  • record (Dnsruby::RR)

    Record to add

  • expire (Fixnum) (defaults to: 0)

    Time in seconds when record becomes stale


123
124
125
126
127
# File 'lib/rex/proto/dns/server.rb', line 123

def add(record, expire = 0)
  self.lock.synchronize do
    self.records[record] = expire
  end
end

#add_static(name, address, type = 'A', replace = false) ⇒ Object

Add static record to cache

Parameters:

  • name (String)

    Name of record

  • address (String)

    Address of record

  • type (String) (defaults to: 'A')

    Record type to add


68
69
70
71
72
73
74
75
76
77
78
# File 'lib/rex/proto/dns/server.rb', line 68

def add_static(name, address, type = 'A', replace = false)
  if Rex::Socket.is_ip_addr?(address.to_s) and
  ( name.to_s.match(MATCH_HOSTNAME) or name == '*')
    find(name, type).each do |found|
      delete(found)
    end if replace
    add(Dnsruby::RR.create(name: name, type: type, address: address),0)
  else
    raise "Invalid parameters for static entry - #{name}, #{address}, #{type}"
  end
end

#cache_record(record) ⇒ Object

Add record to cache, only when “running”

Parameters:

  • record (Dnsruby::RR)

    Record to cache


51
52
53
54
55
56
57
58
59
60
# File 'lib/rex/proto/dns/server.rb', line 51

def cache_record(record)
  return unless @monitor_thread
  if record.is_a?(Dnsruby::RR) and
  (!record.respond_to?(:address) or Rex::Socket.is_ip_addr?(record.address.to_s)) and
  record.name.to_s.match(MATCH_HOSTNAME)
    add(record, ::Time.now.to_i + record.ttl)
  else
    raise "Invalid record for cache entry - #{record.inspect}"
  end
end

#delete(record) ⇒ Object (protected)

Delete a record from the cache with thread safety

Parameters:

  • record (Dnsruby::RR)

    Record to delete


133
134
135
136
137
# File 'lib/rex/proto/dns/server.rb', line 133

def delete(record)
  self.lock.synchronize do
    self.records.delete(record)
  end
end

#find(search, type = 'A') ⇒ Array

Find entries in cache, substituting names for '*' in return

Parameters:

  • search (String)

    Name or address to search for

  • type (String) (defaults to: 'A')

    Record type to search for

Returns:

  • (Array)

    Records found


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/rex/proto/dns/server.rb', line 30

def find(search, type = 'A')
  self.records.select do |record,expire|
    record.type == type and (expire < 1 or expire > ::Time.now.to_i) and
    (
      record.name == '*' or
      record.name == search or record.name[0..-2] == search or
      ( record.respond_to?(:address) and record.address.to_s == search )
    )
  end.keys.map do |record|
    if search.to_s.match(MATCH_HOSTNAME) and record.name == '*'
      record = Dnsruby::RR.create(name: name, type: type, address: address)
    else
      record
    end
  end
end

#prune(before = ::Time.now.to_i) ⇒ Object

Prune cache entries

Parameters:

  • before (Fixnum) (defaults to: ::Time.now.to_i)

    Time in seconds before which records are evicted


84
85
86
87
88
# File 'lib/rex/proto/dns/server.rb', line 84

def prune(before = ::Time.now.to_i)
  self.records.select do |rec, expire|
    expire > 0 and expire < before
  end.each {|rec, exp| delete(rec)}
end

#startObject

Start the cache monitor


93
94
95
96
97
98
99
100
# File 'lib/rex/proto/dns/server.rb', line 93

def start
  @monitor_thread = Rex::ThreadFactory.spawn("DNSServerCacheMonitor", false) {
    while true
      prune
      Rex::ThreadSafe.sleep(0.5)
    end
  } unless @monitor_thread
end

#stop(flush = false) ⇒ Object

Stop the cache monitor

Parameters:

  • flush (TrueClass, FalseClass) (defaults to: false)

    Remove non-static entries


106
107
108
109
110
111
112
113
114
# File 'lib/rex/proto/dns/server.rb', line 106

def stop(flush = false)
  self.monitor_thread.kill unless @monitor_thread.nil?
  @monitor_thread = nil
  if flush
    self.records.select do |rec, expire|
      rec.ttl > 0
    end.each {|rec| delete(rec)}
  end
end