I had started actively contributing to Beeswarm and as I had mentioned before I was working on adding pyFTPdlib 1.0 support. Turns out, since we we only using a rather small part of it, I didn't have to do a whole lot of changes. In the end I ended up adding support for a custom FTP banner, which wasn't much work really. But I did get to learn a lot more about the whole development process. I especially got to know a lot more of git.
I then took up the task of adding support for HTTP 'Basic' Authorization, as detailed in RFC 2617. Since I have already written a brute-forcer for HTTP-Proxy Authorization, I thought this would not be very hard to implement, considering Python's extensive HTTP support. I had anticipated a few snags though, since I had to integrate this with HiveStreamServer, whereas the documentation mostly consists of examples which use SocketServer.TCPServer. Since the request handling is done by BaseHTTPServer, I tried to integrate it with Beeswarm. This led to a situation where I had two different servers running (for the HTTP capability). Here's the code for the capability itself:
class http(HandlerBase):
"""The HTTP Capability"""
def __init__(self, sessions, options):
super(http, self).__init__(sessions, options)
self._options = options
def handle_session(self, gsocket, address):
session = self.create_session(address, gsocket)
handler = BeeHTTPHandler(gsocket, address, None, httpsession = session,
options = self._options)
Here the gsocket is the one created by the Hive, for my capability. The problem I ran into was, that there was no way of passing my own socket to the BaseHTTPServer class. I was rather stuck over here, but then the Lead Developer (who's been mentoring me), pointed out that I can use the *Handler classes without a Server, by instantiating them directly, with the first argument as our socket. Once this was figured out, it was pretty straightforward writing the BeeHTTPHandler class.
class BeeHTTPHandler(BaseHTTPRequestHandler):
def __init__(self, request, client_address, server, httpsession, options):
self._options = options
if self._options.has_key('banner'):
self._banner = self._options['banner']
else:
self._banner = "Microsoft-IIS/5.0"
self._session = httpsession
BaseHTTPRequestHandler.__init__(self, request, client_address, server)
def do_HEAD(self):
...
def do_AUTHHEAD(self):
...
def do_GET(self):
...
The do_* methods are pretty standard, so I won't bother elaborating on those. The interesting part is where I had to call the parent constructor after initializing a few attributes, since it calls methods which use these attributes. I added support for a user-definable 'banner' which will allow the Hive to 'impersonate' other servers, such as Microsoft-IIS or Apache. I also wrote a unittest, which uses the httplib to connect to the server and verifies whether the server is sending 401-Unauthorized status code.