burp-ui/burpui/server.py
2016-01-18 21:43:40 +01:00

290 lines
9.8 KiB
Python

# -*- coding: utf8 -*-
"""
.. module:: burpui.server
:platform: Unix
:synopsis: Burp-UI server module.
.. moduleauthor:: Ziirish <hi+burpui@ziirish.me>
"""
import traceback
import sys
import os
from .misc.auth.handler import UserAuthHandler
from ._compat import ConfigParser
from flask import Flask
g_port = '5000'
g_bind = '::'
g_refresh = '180'
g_liverefresh = '5'
g_ssl = 'False'
g_standalone = 'True'
g_sslcert = ''
g_sslkey = ''
g_version = '1'
g_auth = 'basic'
g_acl = ''
g_storage = ''
g_redis = ''
g_zip64 = 'False'
g_scookie = 'False'
class BUIServer(Flask):
"""
The :class:`burpui.server.BUIServer` class provides the ``Burp-UI`` server.
"""
gunicorn = False
def __init__(self):
"""The :class:`burpui.server.BUIServer` class provides the ``Burp-UI``
server.
:param app: The Flask application to launch
"""
self.init = False
super(BUIServer, self).__init__(__name__)
def setup(self, conf=None):
"""The :func:`burpui.server.BUIServer.setup` functions is used to setup
the whole server by parsing the configuration file and loading the
different backends.
:param conf: Path to a configuration file
:type conf: str
"""
self.sslcontext = None
if not conf:
conf = self.config['CFG']
if not conf:
raise IOError('No configuration file found')
self.defaults = {
'port': g_port, 'bind': g_bind,
'refresh': g_refresh, 'ssl': g_ssl, 'sslcert': g_sslcert,
'sslkey': g_sslkey, 'version': g_version, 'auth': g_auth,
'standalone': g_standalone, 'acl': g_acl,
'liverefresh': g_liverefresh, 'storage': g_storage,
'redis': g_redis, 'zip64': g_zip64, 'scookie': g_scookie
}
config = ConfigParser.ConfigParser(self.defaults)
with open(conf) as fp:
config.readfp(fp)
try:
self.port = self._safe_config_get(
config.getint,
'port',
cast=int
)
self.bind = self._safe_config_get(config.get, 'bind')
self.vers = self._safe_config_get(
config.getint,
'version',
cast=int
)
self.ssl = self._safe_config_get(
config.getboolean,
'ssl',
cast=bool
)
self.standalone = self._safe_config_get(
config.getboolean,
'standalone',
cast=bool
)
self.sslcert = self._safe_config_get(config.get, 'sslcert')
self.sslkey = self._safe_config_get(config.get, 'sslkey')
self.auth = self._safe_config_get(config.get, 'auth')
if self.auth and self.auth.lower() != 'none':
try:
self.uhandler = UserAuthHandler(self)
except Exception as e:
self.logger.error(
'Import Exception, module \'{0}\': {1}'.format(
self.auth,
str(e)
)
)
raise e
self.acl_engine = self._safe_config_get(config.get, 'acl')
else:
# I know that's ugly, but hey, I need it!
self.login_manager._login_disabled = True
# No login => no ACL
self.acl_engine = 'none'
self.auth = 'none'
if self.acl_engine and self.acl_engine.lower() != 'none':
try:
# Try to load submodules from our current environment
# first
sys.path.insert(
0,
os.path.dirname(os.path.abspath(__file__))
)
mod = __import__(
'burpui.misc.acl.{0}'.format(
self.acl_engine.lower()
),
fromlist=['ACLloader']
)
ACLloader = mod.ACLloader
self.acl_handler = ACLloader(self)
# for development purpose only
from .misc.acl.interface import BUIacl
self.acl = BUIacl
self.acl = self.acl_handler.acl
except Exception as e:
self.logger.error(
'Import Exception, module \'{0}\': {1}'.format(
self.acl_engine,
str(e)
)
)
raise e
else:
self.acl_handler = False
self.acl = False
# UI options
self.config['REFRESH'] = self._safe_config_get(
config.getint,
'refresh',
'UI',
cast=int
)
self.config['LIVEREFRESH'] = self._safe_config_get(
config.getint,
'liverefresh',
'UI',
cast=int
)
# Production options
self.storage = self._safe_config_get(
config.get,
'storage',
'Production'
)
self.redis = self._safe_config_get(
config.get,
'redis',
'Production'
)
self.scookie = self._safe_config_get(
config.getboolean,
'scookie',
'Production',
cast=bool
)
# Experimental features
self.zip64 = self._safe_config_get(
config.getboolean,
'zip64',
'Experimental',
cast=bool
)
except ConfigParser.NoOptionError as e:
self.logger.error(str(e))
self.config['STANDALONE'] = self.standalone
self.logger.info('burp version: {}'.format(self.vers))
self.logger.info('listen port: {}'.format(self.port))
self.logger.info('bind addr: {}'.format(self.bind))
self.logger.info('use ssl: {}'.format(self.ssl))
self.logger.info('standalone: {}'.format(self.standalone))
self.logger.info('sslcert: {}'.format(self.sslcert))
self.logger.info('sslkey: {}'.format(self.sslkey))
self.logger.info('refresh: {}'.format(self.config['REFRESH']))
self.logger.info('liverefresh: {}'.format(self.config['LIVEREFRESH']))
self.logger.info('auth: {}'.format(self.auth))
self.logger.info('acl: {}'.format(self.acl_engine))
self.logger.info('zip64: {}'.format(self.zip64))
if self.standalone:
module = 'burpui.misc.backend.burp{0}'.format(self.vers)
else:
module = 'burpui.misc.backend.multi'
# This instanciation is used for development purpose only
from .misc.backend.burp1 import Burp as BurpGeneric
self.cli = BurpGeneric(dummy=True)
try:
# Try to load submodules from our current environment
# first
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
mod = __import__(module, fromlist=['Burp'])
Client = mod.Burp
self.cli = Client(self, conf=conf)
except Exception as e:
traceback.print_exc()
self.logger.error(
'Failed loading backend for Burp version {0}: {1}'.format(
self.vers,
str(e)
)
)
sys.exit(2)
self.init = True
def _safe_config_get(self, callback, key, sect='Global', cast=None):
""":func:`burpui.server.BUIServer._safe_config_get` is a wrapper to
handle Exceptions throwed by :mod:`ConfigParser`.
:param callback: Function to wrap
:type callback: callable
:param key: Key to retrieve
:type key: str
:param sect: Section of the config file to read
:type sect: str
:param cast: Cast the returned value if provided
:type case: callable
:returns: The value returned by the `callback`
"""
try:
return callback(sect, key)
except ConfigParser.NoOptionError as e:
self.logger.error(str(e))
except ConfigParser.NoSectionError as e:
self.logger.warning(str(e))
if key in self.defaults:
if cast:
try:
return cast(self.defaults[key])
except ValueError:
return None
return self.defaults[key]
return None
def manual_run(self):
"""The :func:`burpui.server.BUIServer.manual_run` functions is used to
actually launch the ``Burp-UI`` server.
"""
if not self.init:
self.setup()
if self.ssl:
self.sslcontext = (self.sslcert, self.sslkey)
if self.sslcontext:
self.config['SSL'] = True
self.run(
host=self.bind,
port=self.port,
debug=self.config['DEBUG'],
ssl_context=self.sslcontext
)
else:
self.run(host=self.bind, port=self.port, debug=self.config['DEBUG'])