import copy import datetime import os import random from OpenSSL import SSL from OpenSSL import crypto from pappyproxy import config from pappyproxy import context from pappyproxy import http from pappyproxy.util import PappyException, printable_data from twisted.internet import defer from twisted.internet import reactor, ssl from twisted.internet.protocol import ClientFactory, ServerFactory from twisted.protocols.basic import LineReceiver next_connection_id = 1 cached_certs = {} def get_next_connection_id(): global next_connection_id ret_id = next_connection_id next_connection_id += 1 return ret_id def add_intercepting_macro(key, macro, int_macro_dict): if key in int_macro_dict: raise PappyException('Macro with key %s already exists' % key) int_macro_dict[key] = macro def remove_intercepting_macro(key, int_macro_dict): if not key in int_macro_dict: raise PappyException('Macro with key %s not currently running' % key) del int_macro_dict[key] def log(message, id=None, symbol='*', verbosity_level=1): if config.DEBUG_TO_FILE and not os.path.exists(config.DEBUG_DIR): os.makedirs(config.DEBUG_DIR) if id: debug_str = '[%s](%d) %s' % (symbol, id, message) if config.DEBUG_TO_FILE: with open(config.DEBUG_DIR+'/connection_%d.log' % id, 'a') as f: f.write(debug_str+'\n') else: debug_str = '[%s] %s' % (symbol, message) if config.DEBUG_TO_FILE: with open(config.DEBUG_DIR+'/debug.log', 'a') as f: f.write(debug_str+'\n') if config.DEBUG_VERBOSITY >= verbosity_level: print debug_str def log_request(request, id=None, symbol='*', verbosity_level=3): r_split = request.split('\r\n') for l in r_split: log(l, id, symbol, verbosity_level) class ClientTLSContext(ssl.ClientContextFactory): isClient = 1 def getContext(self): return SSL.Context(SSL.TLSv1_METHOD) class ProxyClient(LineReceiver): def __init__(self, request): self.factory = None self._response_sent = False self._sent = False self.request = request self.data_defer = defer.Deferred() self._response_obj = http.Response() def log(self, message, symbol='*', verbosity_level=1): log(message, id=self.factory.connection_id, symbol=symbol, verbosity_level=verbosity_level) def lineReceived(self, *args, **kwargs): line = args[0] if line is None: line = '' self._response_obj.add_line(line) self.log(line, symbol='r<', verbosity_level=3) if self.factory.stream_response: self.log('Returning line back through stream') self.factory.return_transport.write(line+'\r\n') else: self.log('Not streaming, not returning') self.log(self.factory.stream_response) if self._response_obj.headers_complete: if self._response_obj.complete: self.handle_response_end() return self.log("Headers end, length given, waiting for data", verbosity_level=3) self.setRawMode() def rawDataReceived(self, *args, **kwargs): data = args[0] self.log('Returning data back through stream') if self.factory.stream_response: self.factory.return_transport.write(data) if not self._response_obj.complete: if data: s = printable_data(data) dlines = s.split('\n') for l in dlines: self.log(l, symbol='