Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTPListener can manage HTTP raw files #64

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions fakenet/defaultFiles/generate_204.RAW
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
HTTP/1.0 204 No Content
Content-Length: 0
Date: <RAW-DATE>

13 changes: 13 additions & 0 deletions fakenet/defaultFiles/success.txt.RAW
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 8
Last-Modified: Mon, 15 May 2017 18:04:40 GMT
ETag: "ae780585f49b94ce1444eb7d28906123"
Accept-Ranges: bytes
Server: AmazonS3
X-Amz-Cf-Id: DOMFBGDxBc9xK7seJjwbgRcfGUMjatIzbXRAY4nKJan2KJgKx6nM9g==
Cache-Control: no-cache, no-store, must-revalidate
Date: <RAW-DATE>
Connection: close

success
81 changes: 51 additions & 30 deletions fakenet/listeners/HTTPListener.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
class HTTPListener():

def taste(self, data, dport):
request_methods = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'TRACE',

request_methods = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'TRACE',
'OPTIONS', 'CONNECT', 'PATCH']

confidence = 1 if dport in [80, 443] else 0
Expand All @@ -53,15 +53,15 @@ def taste(self, data, dport):
})

def __init__(
self,
config={},
name='HTTPListener',
logging_level=logging.DEBUG,
self,
config={},
name='HTTPListener',
logging_level=logging.DEBUG,
):

self.logger = logging.getLogger(name)
self.logger.setLevel(logging_level)

self.config = config
self.name = name
self.local_ip = '0.0.0.0'
Expand All @@ -83,7 +83,7 @@ def __init__(

def start(self):
self.logger.debug('Starting...')

self.server = ThreadedHTTPServer((self.local_ip, int(self.config.get('port'))), ThreadedHTTPRequestHandler)
self.server.logger = self.logger
self.server.config = self.config
Expand Down Expand Up @@ -163,10 +163,13 @@ def do_GET(self):
response, response_type = self.get_response(self.path)

# Prepare response
self.send_response(200)
self.send_header("Content-Type", response_type)
self.send_header("Content-Length", len(response))
self.end_headers()
# If response_type is empty, this means that a RAW HTML file
# has been used, so no need for headers
if response_type != '':
self.send_response(200)
self.send_header("Content-Type", response_type)
self.send_header("Content-Length", len(response))
self.end_headers()

self.wfile.write(response)

Expand Down Expand Up @@ -201,16 +204,19 @@ def do_POST(self):

http_f.close()
else:
self.server.logger.error('Failed to write HTTP POST headers and data to %s.', http_filename)
self.server.logger.error('Failed to write HTTP POST headers and data to %s.', http_filename)

# Get response type based on the requested path
response, response_type = self.get_response(self.path)

# Prepare response
self.send_response(200)
self.send_header("Content-Type", response_type)
self.send_header("Content-Length", len(response))
self.end_headers()
# If response_type is empty, this means that a RAW HTML file
# has been used, so no need for headers
if response_type != '':
self.send_response(200)
self.send_header("Content-Type", response_type)
self.send_header("Content-Length", len(response))
self.end_headers()

self.wfile.write(response)

Expand All @@ -229,7 +235,7 @@ def get_response(self, path):
response_filename = ListenerBase.safe_join(self.server.webroot_path, path)

# Check the requested path exists
if not os.path.exists(response_filename):
if not os.path.exists(response_filename) and not os.path.exists(response_filename + '.RAW'):

self.server.logger.debug('Could not find path: %s', response_filename)

Expand All @@ -241,17 +247,32 @@ def get_response(self, path):
self.server.logger.debug('Could not find path: %s', response_filename)
self.server.logger.error('Could not locate requested file or default handler.')
return (response, response_type)

self.server.logger.info('Responding with mime type: %s file: %s', response_type, response_filename)

try:
f = open(response_filename, 'rb')
except Exception, e:
self.server.logger.error('Failed to open response file: %s', response_filename)
response_type = 'text/html'
else:
response = f.read()
f.close()
else:
# RAW file
# if a file named <requestedfile>.RAW exists, it will be sent as it is
# without any additional headers
#
# in the file you can use the following placeholders replaced at runtime
# <RAW-DATE> current time and date
# ...
if os.path.exists(response_filename + '.RAW'):
response_filename = response_filename + '.RAW'
response_type= ''

self.server.logger.info('Responding with mime type: %s file: %s', response_type, response_filename)

try:
f = open(response_filename, 'rb')
except Exception, e:
self.server.logger.error('Failed to open response file: %s', response_filename)
response_type = 'text/html'
else:
response = f.read()
if response_type == '':
# RAW file placeholders replacement
current_time = time.strftime("%a, %-d %b %Y %H:%M:%S %Z")
response = response.replace('<RAW-DATE>',current_time)
f.close()

return (response, response_type)

Expand Down Expand Up @@ -290,7 +311,7 @@ def main():

"""
logging.basicConfig(format='%(asctime)s [%(name)15s] %(message)s', datefmt='%m/%d/%y %I:%M:%S %p', level=logging.DEBUG)

config = {'port': '8443', 'usessl': 'Yes', 'webroot': 'fakenet/defaultFiles' }

listener = HTTPListener(config)
Expand Down