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


20
21
22
23
# File 'lib/rex/proto/dns/server.rb', line 20

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

Instance Attribute Details

#lockObject (readonly)

Returns the value of attribute lock


14
15
16
# File 'lib/rex/proto/dns/server.rb', line 14

def lock
  @lock
end

#monitor_threadObject (readonly)

Returns the value of attribute monitor_thread


14
15
16
# File 'lib/rex/proto/dns/server.rb', line 14

def monitor_thread
  @monitor_thread
end

#recordsObject (readonly)

Returns the value of attribute records


14
15
16
# File 'lib/rex/proto/dns/server.rb', line 14

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


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

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


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

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


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

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


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

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


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

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


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

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


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

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


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

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