Class: Rex::Proto::Http::Packet
- Inherits:
-
Object
- Object
- Rex::Proto::Http::Packet
- Defined in:
- lib/rex/proto/http/packet.rb
Overview
This class represents an HTTP packet.
Defined Under Namespace
Modules: ParseCode, ParseState Classes: Header, UnitTest
Instance Attribute Summary collapse
-
#auto_cl ⇒ Object
Returns the value of attribute auto_cl.
-
#body ⇒ Object
Returns the value of attribute body.
-
#bufq ⇒ Object
Returns the value of attribute bufq.
-
#chunk_max_size ⇒ Object
Returns the value of attribute chunk_max_size.
-
#chunk_min_size ⇒ Object
Returns the value of attribute chunk_min_size.
-
#compress ⇒ Object
Returns the value of attribute compress.
-
#error ⇒ Object
Returns the value of attribute error.
-
#headers ⇒ Object
Returns the value of attribute headers.
-
#incomplete ⇒ Object
readonly
Returns the value of attribute incomplete.
-
#max_data ⇒ Object
Returns the value of attribute max_data.
-
#state ⇒ Object
Returns the value of attribute state.
-
#transfer_chunked ⇒ Object
Returns the value of attribute transfer_chunked.
Instance Method Summary collapse
-
#[](key) ⇒ Object
Return the associated header value, if any.
-
#[]=(key, value) ⇒ Object
Set the associated header value.
-
#chunk(str, min_size = 1, max_size = 1000) ⇒ Object
Build a ‘Transfer-Encoding: chunked’ payload with random chunk sizes.
-
#cmd_string ⇒ Object
Returns the command string, such as:.
-
#completed? ⇒ Boolean
Returns whether or not parsing has completed.
-
#from_s(str) ⇒ Object
Converts the packet from a string.
-
#initialize ⇒ Packet
constructor
Initializes an instance of an HTTP packet.
-
#parse(buf) ⇒ Object
Parses the supplied buffer.
-
#reset ⇒ Object
Reset the parsing state and buffers.
-
#reset_except_queue ⇒ Object
Reset the parsing state but leave the buffers.
-
#to_s ⇒ Object
Converts the packet to a string.
Constructor Details
#initialize ⇒ Packet
Initializes an instance of an HTTP packet.
39 40 41 42 43 44 |
# File 'lib/rex/proto/http/packet.rb', line 39 def initialize() self.headers = Header.new self.auto_cl = true reset end |
Instance Attribute Details
#auto_cl ⇒ Object
Returns the value of attribute auto_cl.
232 233 234 |
# File 'lib/rex/proto/http/packet.rb', line 232 def auto_cl @auto_cl end |
#body ⇒ Object
Returns the value of attribute body.
231 232 233 |
# File 'lib/rex/proto/http/packet.rb', line 231 def body @body end |
#bufq ⇒ Object
Returns the value of attribute bufq.
230 231 232 |
# File 'lib/rex/proto/http/packet.rb', line 230 def bufq @bufq end |
#chunk_max_size ⇒ Object
Returns the value of attribute chunk_max_size.
239 240 241 |
# File 'lib/rex/proto/http/packet.rb', line 239 def chunk_max_size @chunk_max_size end |
#chunk_min_size ⇒ Object
Returns the value of attribute chunk_min_size.
238 239 240 |
# File 'lib/rex/proto/http/packet.rb', line 238 def chunk_min_size @chunk_min_size end |
#compress ⇒ Object
Returns the value of attribute compress.
235 236 237 |
# File 'lib/rex/proto/http/packet.rb', line 235 def compress @compress end |
#error ⇒ Object
Returns the value of attribute error.
228 229 230 |
# File 'lib/rex/proto/http/packet.rb', line 228 def error @error end |
#headers ⇒ Object
Returns the value of attribute headers.
227 228 229 |
# File 'lib/rex/proto/http/packet.rb', line 227 def headers @headers end |
#incomplete ⇒ Object
Returns the value of attribute incomplete.
236 237 238 |
# File 'lib/rex/proto/http/packet.rb', line 236 def incomplete @incomplete end |
#max_data ⇒ Object
Returns the value of attribute max_data.
233 234 235 |
# File 'lib/rex/proto/http/packet.rb', line 233 def max_data @max_data end |
#state ⇒ Object
Returns the value of attribute state.
229 230 231 |
# File 'lib/rex/proto/http/packet.rb', line 229 def state @state end |
#transfer_chunked ⇒ Object
Returns the value of attribute transfer_chunked.
234 235 236 |
# File 'lib/rex/proto/http/packet.rb', line 234 def transfer_chunked @transfer_chunked end |
Instance Method Details
#[](key) ⇒ Object
Return the associated header value, if any.
49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/rex/proto/http/packet.rb', line 49 def [](key) if (self.headers.include?(key)) return self.headers[key] end self.headers.each_pair do |k,v| if (k.downcase == key.downcase) return v end end return nil end |
#[]=(key, value) ⇒ Object
Set the associated header value.
66 67 68 |
# File 'lib/rex/proto/http/packet.rb', line 66 def []=(key, value) self.headers[key] = value end |
#chunk(str, min_size = 1, max_size = 1000) ⇒ Object
Build a ‘Transfer-Encoding: chunked’ payload with random chunk sizes
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/rex/proto/http/packet.rb', line 149 def chunk(str, min_size = 1, max_size = 1000) chunked = '' # min chunk size is 1 byte if (min_size < 1); min_size = 1; end # don't be dumb if (max_size < min_size); max_size = min_size; end while (str.size > 0) chunk = str.slice!(0, rand(max_size - min_size) + min_size) chunked += sprintf("%x", chunk.size) + "\r\n" + chunk + "\r\n" end chunked += "0\r\n\r\n" end |
#cmd_string ⇒ Object
Returns the command string, such as:
HTTP/1.0 200 OK for a response
or
GET /foo HTTP/1.0 for a request
223 224 225 |
# File 'lib/rex/proto/http/packet.rb', line 223 def cmd_string self.headers.cmd_string end |
#completed? ⇒ Boolean
Returns whether or not parsing has completed.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/rex/proto/http/packet.rb', line 131 def completed? return true if self.state == ParseState::Completed # If the parser state is processing the body and there are an # undetermined number of bytes left to read, we just need to say that # things are completed as it's hard to tell whether or not they really # are. if (self.state == ParseState::ProcessingBody and self.body_bytes_left < 0) return true end false end |
#from_s(str) ⇒ Object
Converts the packet from a string.
209 210 211 212 |
# File 'lib/rex/proto/http/packet.rb', line 209 def from_s(str) reset parse(str) end |
#parse(buf) ⇒ Object
Parses the supplied buffer. Returns one of the two parser processing codes (Completed, Partial, or Error).
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/rex/proto/http/packet.rb', line 74 def parse(buf) # Append the incoming buffer to the buffer queue. self.bufq += buf.to_s begin # Process the header if(self.state == ParseState::ProcessingHeader) parse_header end # Continue on to the body if the header was processed if(self.state == ParseState::ProcessingBody) # Chunked encoding sets the parsing state on its own if (self.body_bytes_left == 0 and not self.transfer_chunked) self.state = ParseState::Completed else parse_body end end rescue # XXX: BUG: This rescue might be a problem because it will swallow TimeoutError self.error = $! return ParseCode::Error end # Return completed or partial to the parsing status to the caller (self.state == ParseState::Completed) ? ParseCode::Completed : ParseCode::Partial end |
#reset ⇒ Object
Reset the parsing state and buffers.
108 109 110 111 112 113 114 115 |
# File 'lib/rex/proto/http/packet.rb', line 108 def reset self.state = ParseState::ProcessingHeader self.transfer_chunked = false self.inside_chunk = false self.headers.reset self.bufq = '' self.body = '' end |
#reset_except_queue ⇒ Object
Reset the parsing state but leave the buffers.
120 121 122 123 124 125 126 |
# File 'lib/rex/proto/http/packet.rb', line 120 def reset_except_queue self.state = ParseState::ProcessingHeader self.transfer_chunked = false self.inside_chunk = false self.headers.reset self.body = '' end |
#to_s ⇒ Object
Converts the packet to a string.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/rex/proto/http/packet.rb', line 168 def to_s content = self.body.dup # Update the content length field in the header with the body length. if (content) if !self.compress.nil? case self.compress when 'gzip' self.headers['Content-Encoding'] = 'gzip' content = Rex::Text.gzip(content) when 'deflate' self.headers['Content-Encoding'] = 'deflate' content = Rex::Text.zlib_deflate(content) when 'none' # this one is fine... # when 'compress' else raise RuntimeError, 'Invalid Content-Encoding' end end if (self.auto_cl == true && self.transfer_chunked == true) raise RuntimeError, "'Content-Length' and 'Transfer-Encoding: chunked' are incompatible" elsif self.auto_cl == true self.headers['Content-Length'] = content.length elsif self.transfer_chunked == true if self.proto != '1.1' raise RuntimeError, 'Chunked encoding is only available via 1.1' end self.headers['Transfer-Encoding'] = 'chunked' content = self.chunk(content, self.chunk_min_size, self.chunk_max_size) end end str = self.headers.to_s(cmd_string) str += content || '' end |