#!/usr/bin/env python3
"""
HTTPS Fuzzer using JRSFuzz
by Javantea
Nov 11, 2015
HTTP Fuzzer using JRSFuzz
by Javantea
Nov 11, 2015
Based on SMTP Fuzzer using JRSFuzz
by Javantea
Oct 11, 2015
Based on SMTP Grammar Fuzzer
by Javantea
Sept 14, 2015

For SSL, see https_jrsfuzz1.py

TODO:
POST
Headers
Body
advanced HTTP commands.
Handle errors returned by the server.
Monitors with GDB and ASAN integration.
"""
import jrsfuzz
import sys
import socket
import time
import ssl

def main():
	# This works on any server except those that require STARTTLS (suzy)
	data = open('http1.txt','rb').read()
	host, port = 'localhost', 5001
	if len(sys.argv) > 1:
			host = sys.argv[1]
	#end if
	if len(sys.argv) > 2:
			port = int(sys.argv[2])
	#end if
	print(host, port)
	dest = (host, port)
	family, socktype = socket.AF_UNSPEC, socket.SOCK_STREAM
	gai = socket.getaddrinfo(host, port, family, socktype)
	
	if len(sys.argv) > 3:
		data = sys.argv[3]
	#end if
	lines_output = len(data) * 256
	print("%i outputs, %3.3f MB" % (lines_output, lines_output*len(data)/(1<<20)), file=sys.stderr)

	our_data = None
	for family, socktype, proto, canonname, addr in gai:
		try:
			s = socket.socket(family, socktype, proto)
			s.settimeout(1)
			s.connect(addr)
		except Exception as e:
			print(e,)
			continue
		#end try
		our_data = (family, socktype, proto, canonname, addr)
		break
	#next family, socktype, proto, canonname, addr
	
	if our_data == None:
		print("Can't connect to dest", dest)
	#end if
	family, socktype, proto, canonname, addr = our_data
	print("Found suitable server:", addr)
	
	prevResp = None
	for i in range(lines_output):
		x = jrsfuzz.JRSFuzz(data, i)
		# We might be sending 2 commands, but let it be.
		s = socket.socket(family, socktype, proto)
		s.settimeout(1)
		try:
			s.connect(addr)
		except OSError as e:
			print("Error: you're playing with resources beyond your wildest imagination.")
			print(e)
			time.sleep(10)
			s.connect(addr)
		#end try
		# NOTE: Forget the security, we just want some TLS v1.2.
		try:
			ss = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, ciphers='HIGH:!aNULL:!MD5:!CAMELLIA:!NULL:!DSS:!kDHr:!kDHd:!kDH:!3DES')
		except ssl.SSLEOFError as see:
			print('ssl.SSLEOFError:', see)
			print(i, x)
			continue
		except ssl.SSLError as se:
			print('ssl.SSLError:', se)
			print(i, x)
			continue
		#end try
		try:
			ss.send(x)
		except BrokenPipeError:
			print("Broken Pipe.", i, x)
		except ConnectionResetError:
			print("Conn Reset.", i, x)
		#end try
		try:
			resp = ss.recv(1024)
		except ConnectionResetError:
			print("Conn Reset on recv.", i, x)
			resp = b''
		except KeyboardInterrupt:
			print("Keyboard Interrupt:", i, x)
			resp = b''
		except socket.timeout:
			print("Timeout", i, x)
			resp = b''
		#end try
		print(resp)
		if resp != prevResp: print(i, x)
		prevResp = resp
		ss.close()
		s.close()
	#next i
#end def main()

if __name__ == '__main__':
	main()
#end if