Class: Rex::Proto::TFTP::Server
- Inherits:
-
Object
- Object
- Rex::Proto::TFTP::Server
- Defined in:
- lib/rex/proto/tftp/server.rb
Overview
TFTP Server class
Instance Attribute Summary collapse
-
#context ⇒ Object
Returns the value of attribute context.
-
#files ⇒ Object
Returns the value of attribute files.
-
#incoming_file_hook ⇒ Object
Returns the value of attribute incoming_file_hook.
-
#listen_host ⇒ Object
Returns the value of attribute listen_host.
-
#listen_port ⇒ Object
Returns the value of attribute listen_port.
-
#sock ⇒ Object
Returns the value of attribute sock.
-
#thread ⇒ Object
Returns the value of attribute thread.
-
#transfers ⇒ Object
Returns the value of attribute transfers.
-
#uploaded ⇒ Object
Returns the value of attribute uploaded.
Instance Method Summary collapse
-
#find_file(fname) ⇒ Object
Find the hash entry for a file that may be offered.
-
#find_file_in_root(fname) ⇒ Object
Find the file in the specified tftp root and add a temporary entry to the files hash.
-
#initialize(port = 69, listen_host = '0.0.0.0', context = {}) ⇒ Server
constructor
A new instance of Server.
-
#register_file(fn, content, once = false) ⇒ Object
Register a filename and content for a client to request.
-
#send_error(from, num) ⇒ Object
Send an error packet w/the specified code and string.
-
#send_packet(from, pkt) ⇒ Object
Send a single packet to the specified host.
-
#set_output_dir(outdir) ⇒ Object
Register a directory to write uploaded files to.
-
#set_tftproot(rootdir) ⇒ Object
Register an entire directory to serve files from.
-
#start ⇒ Object
Start the TFTP server.
-
#stop ⇒ Object
Stop the TFTP server.
Constructor Details
#initialize(port = 69, listen_host = '0.0.0.0', context = {}) ⇒ Server
Returns a new instance of Server.
29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/rex/proto/tftp/server.rb', line 29 def initialize(port = 69, listen_host = '0.0.0.0', context = {}) self.listen_host = listen_host self.listen_port = port self.context = context self.sock = nil @shutting_down = false @output_dir = nil @tftproot = nil self.files = [] self.uploaded = [] self.transfers = [] end |
Instance Attribute Details
#context ⇒ Object
Returns the value of attribute context.
172 173 174 |
# File 'lib/rex/proto/tftp/server.rb', line 172 def context @context end |
#files ⇒ Object
Returns the value of attribute files.
173 174 175 |
# File 'lib/rex/proto/tftp/server.rb', line 173 def files @files end |
#incoming_file_hook ⇒ Object
Returns the value of attribute incoming_file_hook.
176 177 178 |
# File 'lib/rex/proto/tftp/server.rb', line 176 def incoming_file_hook @incoming_file_hook end |
#listen_host ⇒ Object
Returns the value of attribute listen_host.
172 173 174 |
# File 'lib/rex/proto/tftp/server.rb', line 172 def listen_host @listen_host end |
#listen_port ⇒ Object
Returns the value of attribute listen_port.
172 173 174 |
# File 'lib/rex/proto/tftp/server.rb', line 172 def listen_port @listen_port end |
#sock ⇒ Object
Returns the value of attribute sock.
173 174 175 |
# File 'lib/rex/proto/tftp/server.rb', line 173 def sock @sock end |
#thread ⇒ Object
Returns the value of attribute thread.
174 175 176 |
# File 'lib/rex/proto/tftp/server.rb', line 174 def thread @thread end |
#transfers ⇒ Object
Returns the value of attribute transfers.
173 174 175 |
# File 'lib/rex/proto/tftp/server.rb', line 173 def transfers @transfers end |
#uploaded ⇒ Object
Returns the value of attribute uploaded.
173 174 175 |
# File 'lib/rex/proto/tftp/server.rb', line 173 def uploaded @uploaded end |
Instance Method Details
#find_file(fname) ⇒ Object
Find the hash entry for a file that may be offered
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/rex/proto/tftp/server.rb', line 134 def find_file(fname) # Files served via register_file() take precedence. self.files.each do |f| if (fname == f[:name]) return f end end # Now, if we have a tftproot, see if it can serve from it if @tftproot return find_file_in_root(fname) end nil end |
#find_file_in_root(fname) ⇒ Object
Find the file in the specified tftp root and add a temporary entry to the files hash.
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/rex/proto/tftp/server.rb', line 155 def find_file_in_root(fname) fn = ::File.(::File.join(@tftproot, fname)) # Don't allow directory traversal return nil if fn.index(@tftproot) != 0 return nil if not ::File.file?(fn) or not ::File.readable?(fn) # Read the file contents, and register it as being served once data = data = ::File.open(fn, "rb") { |fd| fd.read(fd.stat.size) } register_file(fname, data) # Return the last file in the array return self.files[-1] end |
#register_file(fn, content, once = false) ⇒ Object
Register a filename and content for a client to request
83 84 85 86 87 88 89 |
# File 'lib/rex/proto/tftp/server.rb', line 83 def register_file(fn, content, once = false) self.files << { :name => fn, :data => content, :once => once } end |
#send_error(from, num) ⇒ Object
Send an error packet w/the specified code and string
111 112 113 114 115 116 117 118 119 120 |
# File 'lib/rex/proto/tftp/server.rb', line 111 def send_error(from, num) if (num < 1 or num >= ERRCODES.length) # ignore.. return end pkt = [OpError, num].pack('nn') pkt << ERRCODES[num] pkt << "\x00" send_packet(from, pkt) end |
#send_packet(from, pkt) ⇒ Object
Send a single packet to the specified host
126 127 128 |
# File 'lib/rex/proto/tftp/server.rb', line 126 def send_packet(from, pkt) self.sock.sendto(pkt, from[0], from[1]) end |
#set_output_dir(outdir) ⇒ Object
Register a directory to write uploaded files to
103 104 105 |
# File 'lib/rex/proto/tftp/server.rb', line 103 def set_output_dir(outdir) @output_dir = outdir if ::File.directory?(outdir) end |
#set_tftproot(rootdir) ⇒ Object
Register an entire directory to serve files from
95 96 97 |
# File 'lib/rex/proto/tftp/server.rb', line 95 def set_tftproot(rootdir) @tftproot = rootdir if ::File.directory?(rootdir) end |
#start ⇒ Object
Start the TFTP server
47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/rex/proto/tftp/server.rb', line 47 def start self.sock = Rex::Socket::Udp.create( 'LocalHost' => listen_host, 'LocalPort' => listen_port, 'Context' => context ) self.thread = Rex::ThreadFactory.spawn("TFTPServerMonitor", false) { monitor_socket } end |
#stop ⇒ Object
Stop the TFTP server
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/rex/proto/tftp/server.rb', line 63 def stop @shutting_down = true # Wait a maximum of 30 seconds for all transfers to finish. start = ::Time.now while (self.transfers.length > 0) ::IO.select(nil, nil, nil, 0.5) dur = ::Time.now - start break if (dur > 30) end self.files.clear self.thread.kill self.sock.close rescue nil # might be closed already end |