def test_check_badRSAkey(self): """A challenge with a bad RSA secret key should return False.""" secretKeyBad, publicKeyBad = crypto.getRSAKey('test_gimpCaptcha_badRSAkey') c = captcha.GimpCaptcha(self.publik, self.sekrit, self.hmacKey, self.cacheDir) image, challenge = c.get() self.assertEquals( c.check(challenge, c.answer, secretKeyBad, c.hmacKey), False)
def setUp(self): here = os.getcwd() self.topDir = here.rstrip("_trial_temp") self.cacheDir = os.path.join(self.topDir, "captchas") self.badCacheDir = os.path.join(here, "capt") # Get keys for testing or create them: self.sekrit, self.publik = crypto.getRSAKey("test_gimpCaptcha_RSAkey") self.hmacKey = crypto.getKey("test_gimpCaptcha_HMACkey")
def setUp(self): here = os.getcwd() self.topDir = here.rstrip('_trial_temp') self.cacheDir = os.path.join(self.topDir, 'captchas') self.badCacheDir = os.path.join(here, 'capt') # Get keys for testing or create them: self.sekrit, self.publik = crypto.getRSAKey('test_gimpCaptcha_RSAkey') self.hmacKey = crypto.getKey('test_gimpCaptcha_HMACkey')
def test_check_badRSAkey(self): """A challenge with a bad RSA secret key should return False.""" secretKeyBad, publicKeyBad = crypto.getRSAKey( 'test_gimpCaptcha_badRSAkey') c = captcha.GimpCaptcha(self.publik, self.sekrit, self.hmacKey, self.cacheDir) image, challenge = c.get() self.assertEquals( c.check(challenge, c.answer, secretKeyBad, c.hmacKey), False)
def addWebServer(config, distributor): """Set up a web server for HTTP(S)-based bridge distribution. :type config: :class:`bridgedb.persistent.Conf` :param config: A configuration object from :mod:`bridgedb.Main`. Currently, we use these options:: HTTP_UNENCRYPTED_PORT HTTP_UNENCRYPTED_BIND_IP HTTP_USE_IP_FROM_FORWARDED_HEADER HTTPS_N_BRIDGES_PER_ANSWER HTTPS_INCLUDE_FINGERPRINTS HTTPS_KEY_FILE HTTPS_CERT_FILE HTTPS_PORT HTTPS_BIND_IP HTTPS_USE_IP_FROM_FORWARDED_HEADER HTTPS_ROTATION_PERIOD RECAPTCHA_ENABLED RECAPTCHA_PUB_KEY RECAPTCHA_SEC_KEY RECAPTCHA_REMOTEIP GIMP_CAPTCHA_ENABLED GIMP_CAPTCHA_DIR GIMP_CAPTCHA_HMAC_KEYFILE GIMP_CAPTCHA_RSA_KEYFILE SERVER_PUBLIC_FQDN CSP_ENABLED CSP_REPORT_ONLY CSP_INCLUDE_SELF :type distributor: :class:`bridgedb.https.distributor.HTTPSDistributor` :param distributor: A bridge distributor. :raises SystemExit: if the servers cannot be started. :rtype: :api:`twisted.web.server.Site` :returns: A webserver. """ captcha = None fwdHeaders = config.HTTP_USE_IP_FROM_FORWARDED_HEADER numBridges = config.HTTPS_N_BRIDGES_PER_ANSWER fprInclude = config.HTTPS_INCLUDE_FINGERPRINTS logging.info("Starting web servers...") setFQDN(config.SERVER_PUBLIC_FQDN) index = IndexResource() options = OptionsResource() howto = HowtoResource() robots = static.File(os.path.join(TEMPLATE_DIR, 'robots.txt')) assets = static.File(os.path.join(TEMPLATE_DIR, 'assets/')) keys = static.Data(bytes(strings.BRIDGEDB_OPENPGP_KEY), 'text/plain') csp = CSPResource(enabled=config.CSP_ENABLED, includeSelf=config.CSP_INCLUDE_SELF, reportViolations=config.CSP_REPORT_ONLY, useForwardedHeader=fwdHeaders) root = CustomErrorHandlingResource() root.putChild('', index) root.putChild('robots.txt', robots) root.putChild('keys', keys) root.putChild('assets', assets) root.putChild('options', options) root.putChild('howto', howto) root.putChild('maintenance', maintenance) root.putChild('error', resource500) root.putChild(CSPResource.reportURI, csp) if config.RECAPTCHA_ENABLED: publicKey = config.RECAPTCHA_PUB_KEY secretKey = config.RECAPTCHA_SEC_KEY captcha = partial(ReCaptchaProtectedResource, remoteIP=config.RECAPTCHA_REMOTEIP) elif config.GIMP_CAPTCHA_ENABLED: # Get the master HMAC secret key for CAPTCHA challenges, and then # create a new HMAC key from it for use on the server. captchaKey = crypto.getKey(config.GIMP_CAPTCHA_HMAC_KEYFILE) hmacKey = crypto.getHMAC(captchaKey, "Captcha-Key") # Load or create our encryption keys: secretKey, publicKey = crypto.getRSAKey(config.GIMP_CAPTCHA_RSA_KEYFILE) captcha = partial(GimpCaptchaProtectedResource, hmacKey=hmacKey, captchaDir=config.GIMP_CAPTCHA_DIR) if config.HTTPS_ROTATION_PERIOD: count, period = config.HTTPS_ROTATION_PERIOD.split() sched = ScheduledInterval(count, period) else: sched = Unscheduled() bridges = BridgesResource(distributor, sched, numBridges, fwdHeaders, includeFingerprints=fprInclude) if captcha: # Protect the 'bridges' page with a CAPTCHA, if configured to do so: protected = captcha(publicKey=publicKey, secretKey=secretKey, useForwardedHeader=fwdHeaders, protectedResource=bridges) root.putChild('bridges', protected) logging.info("Protecting resources with %s." % captcha.func.__name__) else: root.putChild('bridges', bridges) site = Site(root) site.displayTracebacks = False if config.HTTP_UNENCRYPTED_PORT: # pragma: no cover ip = config.HTTP_UNENCRYPTED_BIND_IP or "" port = config.HTTP_UNENCRYPTED_PORT or 80 try: reactor.listenTCP(port, site, interface=ip) except CannotListenError as error: raise SystemExit(error) logging.info("Started HTTP server on %s:%d" % (str(ip), int(port))) if config.HTTPS_PORT: # pragma: no cover ip = config.HTTPS_BIND_IP or "" port = config.HTTPS_PORT or 443 try: from twisted.internet.ssl import DefaultOpenSSLContextFactory factory = DefaultOpenSSLContextFactory(config.HTTPS_KEY_FILE, config.HTTPS_CERT_FILE) reactor.listenSSL(port, site, factory, interface=ip) except CannotListenError as error: raise SystemExit(error) logging.info("Started HTTPS server on %s:%d" % (str(ip), int(port))) return site
def addWebServer(cfg, dist, sched): """Set up a web server for HTTP(S)-based bridge distribution. :type cfg: :class:`bridgedb.persistent.Conf` :param cfg: A configuration object from :mod:`bridgedb.Main`. Currently, we use these options:: HTTP_UNENCRYPTED_PORT HTTP_UNENCRYPTED_BIND_IP HTTP_USE_IP_FROM_FORWARDED_HEADER HTTPS_N_BRIDGES_PER_ANSWER HTTPS_INCLUDE_FINGERPRINTS HTTPS_KEY_FILE HTTPS_CERT_FILE HTTPS_PORT HTTPS_BIND_IP HTTPS_USE_IP_FROM_FORWARDED_HEADER RECAPTCHA_ENABLED RECAPTCHA_PUB_KEY RECAPTCHA_SEC_KEY RECAPTCHA_REMOTEIP GIMP_CAPTCHA_ENABLED GIMP_CAPTCHA_DIR GIMP_CAPTCHA_HMAC_KEYFILE GIMP_CAPTCHA_RSA_KEYFILE :type dist: :class:`bridgedb.Dist.IPBasedDistributor` :param dist: A bridge distributor. :type sched: :class:`bridgedb.schedule.ScheduledInterval` :param sched: The scheduled interval at which bridge selection, which are ultimately displayed on the :class:`WebResourceBridges` page, will be shifted. :raises SystemExit: if the servers cannot be started. :rtype: :api:`twisted.web.server.Site` :returns: A webserver. """ captcha = None fwdHeaders = cfg.HTTP_USE_IP_FROM_FORWARDED_HEADER numBridges = cfg.HTTPS_N_BRIDGES_PER_ANSWER fprInclude = cfg.HTTPS_INCLUDE_FINGERPRINTS logging.info("Starting web servers...") httpdist = resource.Resource() httpdist.putChild('', WebRoot()) httpdist.putChild('robots.txt', static.File(os.path.join(TEMPLATE_DIR, 'robots.txt'))) httpdist.putChild('keys', static.File(os.path.join(TEMPLATE_DIR, 'bridgedb.asc'))) httpdist.putChild('assets', static.File(os.path.join(TEMPLATE_DIR, 'assets/'))) httpdist.putChild('options', WebResourceOptions()) httpdist.putChild('howto', WebResourceHowto()) if cfg.RECAPTCHA_ENABLED: publicKey = cfg.RECAPTCHA_PUB_KEY secretKey = cfg.RECAPTCHA_SEC_KEY captcha = partial(ReCaptchaProtectedResource, remoteIP=cfg.RECAPTCHA_REMOTEIP) elif cfg.GIMP_CAPTCHA_ENABLED: # Get the master HMAC secret key for CAPTCHA challenges, and then # create a new HMAC key from it for use on the server. captchaKey = crypto.getKey(cfg.GIMP_CAPTCHA_HMAC_KEYFILE) hmacKey = crypto.getHMAC(captchaKey, "Captcha-Key") # Load or create our encryption keys: secretKey, publicKey = crypto.getRSAKey(cfg.GIMP_CAPTCHA_RSA_KEYFILE) captcha = partial(GimpCaptchaProtectedResource, hmacKey=hmacKey, captchaDir=cfg.GIMP_CAPTCHA_DIR) bridges = WebResourceBridges(dist, sched, numBridges, fwdHeaders, includeFingerprints=fprInclude) if captcha: # Protect the 'bridges' page with a CAPTCHA, if configured to do so: protected = captcha(publicKey=publicKey, secretKey=secretKey, useForwardedHeader=fwdHeaders, protectedResource=bridges) httpdist.putChild('bridges', protected) logging.info("Protecting resources with %s." % captcha.func.__name__) else: httpdist.putChild('bridges', bridges) site = server.Site(httpdist) site.displayTracebacks = False if cfg.HTTP_UNENCRYPTED_PORT: ip = cfg.HTTP_UNENCRYPTED_BIND_IP or "" port = cfg.HTTP_UNENCRYPTED_PORT or 80 try: reactor.listenTCP(port, site, interface=ip) except CannotListenError as error: raise SystemExit(error) logging.info("Started HTTP server on %s:%d" % (str(ip), int(port))) if cfg.HTTPS_PORT: ip = cfg.HTTPS_BIND_IP or "" port = cfg.HTTPS_PORT or 443 try: from twisted.internet.ssl import DefaultOpenSSLContextFactory factory = DefaultOpenSSLContextFactory(cfg.HTTPS_KEY_FILE, cfg.HTTPS_CERT_FILE) reactor.listenSSL(port, site, factory, interface=ip) except CannotListenError as error: raise SystemExit(error) logging.info("Started HTTPS server on %s:%d" % (str(ip), int(port))) return site
def addWebServer(cfg, dist): """Set up a web server for HTTP(S)-based bridge distribution. :type cfg: :class:`bridgedb.persistent.Conf` :param cfg: A configuration object from :mod:`bridgedb.Main`. Currently, we use these options:: HTTP_UNENCRYPTED_PORT HTTP_UNENCRYPTED_BIND_IP HTTP_USE_IP_FROM_FORWARDED_HEADER HTTPS_N_BRIDGES_PER_ANSWER HTTPS_INCLUDE_FINGERPRINTS HTTPS_KEY_FILE HTTPS_CERT_FILE HTTPS_PORT HTTPS_BIND_IP HTTPS_USE_IP_FROM_FORWARDED_HEADER HTTPS_ROTATION_PERIOD RECAPTCHA_ENABLED RECAPTCHA_PUB_KEY RECAPTCHA_SEC_KEY RECAPTCHA_REMOTEIP GIMP_CAPTCHA_ENABLED GIMP_CAPTCHA_DIR GIMP_CAPTCHA_HMAC_KEYFILE GIMP_CAPTCHA_RSA_KEYFILE :type dist: :class:`bridgedb.Dist.IPBasedDistributor` :param dist: A bridge distributor. :raises SystemExit: if the servers cannot be started. :rtype: :api:`twisted.web.server.Site` :returns: A webserver. """ captcha = None fwdHeaders = cfg.HTTP_USE_IP_FROM_FORWARDED_HEADER numBridges = cfg.HTTPS_N_BRIDGES_PER_ANSWER fprInclude = cfg.HTTPS_INCLUDE_FINGERPRINTS logging.info("Starting web servers...") httpdist = resource.Resource() httpdist.putChild('', WebRoot()) httpdist.putChild('robots.txt', static.File(os.path.join(TEMPLATE_DIR, 'robots.txt'))) httpdist.putChild('keys', static.File(os.path.join(TEMPLATE_DIR, 'bridgedb.asc'))) httpdist.putChild('assets', static.File(os.path.join(TEMPLATE_DIR, 'assets/'))) httpdist.putChild('options', WebResourceOptions()) httpdist.putChild('howto', WebResourceHowto()) if cfg.RECAPTCHA_ENABLED: publicKey = cfg.RECAPTCHA_PUB_KEY secretKey = cfg.RECAPTCHA_SEC_KEY captcha = partial(ReCaptchaProtectedResource, remoteIP=cfg.RECAPTCHA_REMOTEIP) elif cfg.GIMP_CAPTCHA_ENABLED: # Get the master HMAC secret key for CAPTCHA challenges, and then # create a new HMAC key from it for use on the server. captchaKey = crypto.getKey(cfg.GIMP_CAPTCHA_HMAC_KEYFILE) hmacKey = crypto.getHMAC(captchaKey, "Captcha-Key") # Load or create our encryption keys: secretKey, publicKey = crypto.getRSAKey(cfg.GIMP_CAPTCHA_RSA_KEYFILE) captcha = partial(GimpCaptchaProtectedResource, hmacKey=hmacKey, captchaDir=cfg.GIMP_CAPTCHA_DIR) if cfg.HTTPS_ROTATION_PERIOD: count, period = cfg.HTTPS_ROTATION_PERIOD.split() sched = ScheduledInterval(count, period) else: sched = Unscheduled() bridges = WebResourceBridges(dist, sched, numBridges, fwdHeaders, includeFingerprints=fprInclude) if captcha: # Protect the 'bridges' page with a CAPTCHA, if configured to do so: protected = captcha(publicKey=publicKey, secretKey=secretKey, useForwardedHeader=fwdHeaders, protectedResource=bridges) httpdist.putChild('bridges', protected) logging.info("Protecting resources with %s." % captcha.func.__name__) else: httpdist.putChild('bridges', bridges) site = server.Site(httpdist) site.displayTracebacks = False if cfg.HTTP_UNENCRYPTED_PORT: ip = cfg.HTTP_UNENCRYPTED_BIND_IP or "" port = cfg.HTTP_UNENCRYPTED_PORT or 80 try: reactor.listenTCP(port, site, interface=ip) except CannotListenError as error: raise SystemExit(error) logging.info("Started HTTP server on %s:%d" % (str(ip), int(port))) if cfg.HTTPS_PORT: ip = cfg.HTTPS_BIND_IP or "" port = cfg.HTTPS_PORT or 443 try: from twisted.internet.ssl import DefaultOpenSSLContextFactory factory = DefaultOpenSSLContextFactory(cfg.HTTPS_KEY_FILE, cfg.HTTPS_CERT_FILE) reactor.listenSSL(port, site, factory, interface=ip) except CannotListenError as error: raise SystemExit(error) logging.info("Started HTTPS server on %s:%d" % (str(ip), int(port))) return site
def addWebServer(cfg, dist, sched): """Set up a web server. :param cfg: A configuration object from :mod:`bridgedb.Main`. Currently, we use these options:: HTTPS_N_BRIDGES_PER_ANSWER HTTP_UNENCRYPTED_PORT HTTP_UNENCRYPTED_BIND_IP HTTP_USE_IP_FROM_FORWARDED_HEADER HTTPS_PORT HTTPS_BIND_IP HTTPS_USE_IP_FROM_FORWARDED_HEADER RECAPTCHA_ENABLED RECAPTCHA_PUB_KEY RECAPTCHA_PRIV_KEY RECAPTCHA_REMOTEIP GIMP_CAPTCHA_ENABLED GIMP_CAPTCHA_DIR :type dist: :class:`bridgedb.Dist.IPBasedDistributor` :param dist: A bridge distributor. :type sched: :class:`bridgedb.Time.IntervalSchedule` :param sched: DOCDOC """ httpdist = resource.Resource() httpdist.putChild('', WebRoot()) httpdist.putChild('robots.txt', static.File(os.path.join(template_root, 'robots.txt'))) httpdist.putChild('assets', static.File(os.path.join(template_root, 'assets/'))) httpdist.putChild('options', WebResourceOptions()) bridgesResource = WebResourceBridges( dist, sched, cfg.HTTPS_N_BRIDGES_PER_ANSWER, cfg.HTTP_USE_IP_FROM_FORWARDED_HEADER, includeFingerprints=cfg.HTTPS_INCLUDE_FINGERPRINTS) if cfg.RECAPTCHA_ENABLED: protected = ReCaptchaProtectedResource( recaptchaPrivKey=cfg.RECAPTCHA_PRIV_KEY, recaptchaPubKey=cfg.RECAPTCHA_PUB_KEY, remoteip=cfg.RECAPTCHA_REMOTEIP, useForwardedHeader=cfg.HTTP_USE_IP_FROM_FORWARDED_HEADER, protectedResource=bridgesResource) httpdist.putChild('bridges', protected) elif cfg.GIMP_CAPTCHA_ENABLED: # Get the HMAC secret key for CAPTCHA challenges and create a new key # from it for use on the server: captchaKey = crypto.getKey(cfg.GIMP_CAPTCHA_HMAC_KEYFILE) hmacKey = crypto.getHMAC(captchaKey, "Captcha-Key") # Load or create our encryption keys: secretKey, publicKey = crypto.getRSAKey(cfg.GIMP_CAPTCHA_RSA_KEYFILE) protected = GimpCaptchaProtectedResource( secretKey=secretKey, publicKey=publicKey, hmacKey=hmacKey, captchaDir=cfg.GIMP_CAPTCHA_DIR, useForwardedHeader=cfg.HTTP_USE_IP_FROM_FORWARDED_HEADER, protectedResource=bridgesResource) httpdist.putChild('bridges', protected) else: httpdist.putChild('bridges', bridgesResource) site = server.Site(httpdist) if cfg.HTTP_UNENCRYPTED_PORT: ip = cfg.HTTP_UNENCRYPTED_BIND_IP or "" try: reactor.listenTCP(cfg.HTTP_UNENCRYPTED_PORT, site, interface=ip) except CannotListenError as error: raise SystemExit(error) if cfg.HTTPS_PORT: from twisted.internet.ssl import DefaultOpenSSLContextFactory #from OpenSSL.SSL import SSLv3_METHOD ip = cfg.HTTPS_BIND_IP or "" factory = DefaultOpenSSLContextFactory(cfg.HTTPS_KEY_FILE, cfg.HTTPS_CERT_FILE) try: reactor.listenSSL(cfg.HTTPS_PORT, site, factory, interface=ip) except CannotListenError as error: raise SystemExit(error) return site
def addWebServer(config, distributor): """Set up a web server for HTTP(S)-based bridge distribution. :type config: :class:`bridgedb.persistent.Conf` :param config: A configuration object from :mod:`bridgedb.main`. Currently, we use these options:: HTTP_UNENCRYPTED_PORT HTTP_UNENCRYPTED_BIND_IP HTTP_USE_IP_FROM_FORWARDED_HEADER HTTPS_N_BRIDGES_PER_ANSWER HTTPS_INCLUDE_FINGERPRINTS HTTPS_KEY_FILE HTTPS_CERT_FILE HTTPS_PORT HTTPS_BIND_IP HTTPS_USE_IP_FROM_FORWARDED_HEADER HTTPS_ROTATION_PERIOD RECAPTCHA_ENABLED RECAPTCHA_PUB_KEY RECAPTCHA_SEC_KEY RECAPTCHA_REMOTEIP GIMP_CAPTCHA_ENABLED GIMP_CAPTCHA_DIR GIMP_CAPTCHA_HMAC_KEYFILE GIMP_CAPTCHA_RSA_KEYFILE SERVER_PUBLIC_FQDN CSP_ENABLED CSP_REPORT_ONLY CSP_INCLUDE_SELF :type distributor: :class:`bridgedb.distributors.https.distributor.HTTPSDistributor` :param distributor: A bridge distributor. :raises SystemExit: if the servers cannot be started. :rtype: :api:`twisted.web.server.Site` :returns: A webserver. """ captcha = None fwdHeaders = config.HTTP_USE_IP_FROM_FORWARDED_HEADER numBridges = config.HTTPS_N_BRIDGES_PER_ANSWER fprInclude = config.HTTPS_INCLUDE_FINGERPRINTS logging.info("Starting web servers...") setFQDN(config.SERVER_PUBLIC_FQDN) index = IndexResource() options = OptionsResource() howto = HowtoResource() robots = static.File(os.path.join(TEMPLATE_DIR, 'robots.txt')) assets = static.File(os.path.join(TEMPLATE_DIR, 'assets/')) keys = static.Data(bytes(strings.BRIDGEDB_OPENPGP_KEY), 'text/plain') csp = CSPResource(enabled=config.CSP_ENABLED, includeSelf=config.CSP_INCLUDE_SELF, reportViolations=config.CSP_REPORT_ONLY, useForwardedHeader=fwdHeaders) root = CustomErrorHandlingResource() root.putChild('', index) root.putChild('robots.txt', robots) root.putChild('keys', keys) root.putChild('assets', assets) root.putChild('options', options) root.putChild('howto', howto) root.putChild('maintenance', maintenance) root.putChild('error', resource500) root.putChild(CSPResource.reportURI, csp) if config.RECAPTCHA_ENABLED: publicKey = config.RECAPTCHA_PUB_KEY secretKey = config.RECAPTCHA_SEC_KEY captcha = partial(ReCaptchaProtectedResource, remoteIP=config.RECAPTCHA_REMOTEIP) elif config.GIMP_CAPTCHA_ENABLED: # Get the master HMAC secret key for CAPTCHA challenges, and then # create a new HMAC key from it for use on the server. captchaKey = crypto.getKey(config.GIMP_CAPTCHA_HMAC_KEYFILE) hmacKey = crypto.getHMAC(captchaKey, "Captcha-Key") # Load or create our encryption keys: secretKey, publicKey = crypto.getRSAKey(config.GIMP_CAPTCHA_RSA_KEYFILE) captcha = partial(GimpCaptchaProtectedResource, hmacKey=hmacKey, captchaDir=config.GIMP_CAPTCHA_DIR) if config.HTTPS_ROTATION_PERIOD: count, period = config.HTTPS_ROTATION_PERIOD.split() sched = ScheduledInterval(count, period) else: sched = Unscheduled() bridges = BridgesResource(distributor, sched, numBridges, fwdHeaders, includeFingerprints=fprInclude) if captcha: # Protect the 'bridges' page with a CAPTCHA, if configured to do so: protected = captcha(publicKey=publicKey, secretKey=secretKey, useForwardedHeader=fwdHeaders, protectedResource=bridges) root.putChild('bridges', protected) logging.info("Protecting resources with %s." % captcha.func.__name__) else: root.putChild('bridges', bridges) site = Site(root) site.displayTracebacks = False if config.HTTP_UNENCRYPTED_PORT: # pragma: no cover ip = config.HTTP_UNENCRYPTED_BIND_IP or "" port = config.HTTP_UNENCRYPTED_PORT or 80 try: reactor.listenTCP(port, site, interface=ip) except CannotListenError as error: raise SystemExit(error) logging.info("Started HTTP server on %s:%d" % (str(ip), int(port))) if config.HTTPS_PORT: # pragma: no cover ip = config.HTTPS_BIND_IP or "" port = config.HTTPS_PORT or 443 try: from twisted.internet.ssl import DefaultOpenSSLContextFactory factory = DefaultOpenSSLContextFactory(config.HTTPS_KEY_FILE, config.HTTPS_CERT_FILE) reactor.listenSSL(port, site, factory, interface=ip) except CannotListenError as error: raise SystemExit(error) logging.info("Started HTTPS server on %s:%d" % (str(ip), int(port))) return site
def addMoatServer(config, distributor): """Set up a web server for moat bridge distribution. :type config: :class:`bridgedb.persistent.Conf` :param config: A configuration object from :mod:`bridgedb.main`. Currently, we use these options:: GIMP_CAPTCHA_DIR SERVER_PUBLIC_FQDN SUPPORTED_TRANSPORTS MOAT_DIST MOAT_DIST_VIA_MEEK_ONLY MOAT_TLS_CERT_FILE MOAT_TLS_KEY_FILE MOAT_SERVER_PUBLIC_ROOT MOAT_HTTPS_IP MOAT_HTTPS_PORT MOAT_HTTP_IP MOAT_HTTP_PORT MOAT_BRIDGES_PER_ANSWER MOAT_TRANSPORT_PREFERENCE_LIST MOAT_USE_IP_FROM_FORWARDED_HEADER MOAT_SKIP_LOOPBACK_ADDRESSES MOAT_ROTATION_PERIOD MOAT_GIMP_CAPTCHA_HMAC_KEYFILE MOAT_GIMP_CAPTCHA_RSA_KEYFILE :type distributor: :class:`bridgedb.distributors.moat.distributor.MoatDistributor` :param distributor: A bridge distributor. :raises SystemExit: if the servers cannot be started. :rtype: :api:`twisted.web.server.Site` :returns: A webserver. """ captcha = None fwdHeaders = config.MOAT_USE_IP_FROM_FORWARDED_HEADER numBridges = config.MOAT_BRIDGES_PER_ANSWER skipLoopback = config.MOAT_SKIP_LOOPBACK_ADDRESSES logging.info("Starting moat servers...") setFQDN(config.SERVER_PUBLIC_FQDN) setRoot(config.MOAT_SERVER_PUBLIC_ROOT) setSupportedTransports(config.SUPPORTED_TRANSPORTS) setPreferredTransports(config.MOAT_TRANSPORT_PREFERENCE_LIST) # Get the master HMAC secret key for CAPTCHA challenges, and then # create a new HMAC key from it for use on the server. captchaKey = crypto.getKey(config.MOAT_GIMP_CAPTCHA_HMAC_KEYFILE) hmacKey = crypto.getHMAC(captchaKey, "Moat-Captcha-Key") # Load or create our encryption keys: secretKey, publicKey = crypto.getRSAKey( config.MOAT_GIMP_CAPTCHA_RSA_KEYFILE) sched = Unscheduled() if config.MOAT_ROTATION_PERIOD: count, period = config.MOAT_ROTATION_PERIOD.split() sched = ScheduledInterval(count, period) sitePublicDir = getRoot() meek = CustomErrorHandlingResource() moat = CustomErrorHandlingResource() fetch = CaptchaFetchResource(hmacKey, publicKey, secretKey, config.GIMP_CAPTCHA_DIR, fwdHeaders, skipLoopback) check = CaptchaCheckResource(distributor, sched, numBridges, hmacKey, publicKey, secretKey, fwdHeaders, skipLoopback) moat.putChild(b"fetch", fetch) moat.putChild(b"check", check) meek.putChild(b"moat", moat) root = CustomErrorHandlingResource() root.putChild(b"meek", meek) root.putChild(b"moat", moat) site = Site(root) site.displayTracebacks = False if config.MOAT_HTTP_PORT: # pragma: no cover ip = config.MOAT_HTTP_IP or "" port = config.MOAT_HTTP_PORT or 80 try: reactor.listenTCP(port, site, interface=ip) except CannotListenError as error: raise SystemExit(error) logging.info("Started Moat HTTP server on %s:%d" % (str(ip), int(port))) if config.MOAT_HTTPS_PORT: # pragma: no cover ip = config.MOAT_HTTPS_IP or "" port = config.MOAT_HTTPS_PORT or 443 try: from twisted.internet.ssl import DefaultOpenSSLContextFactory factory = DefaultOpenSSLContextFactory(config.MOAT_TLS_KEY_FILE, config.MOAT_TLS_CERT_FILE) reactor.listenSSL(port, site, factory, interface=ip) except CannotListenError as error: raise SystemExit(error) logging.info("Started Moat TLS server on %s:%d" % (str(ip), int(port))) return site
def addMoatServer(config, distributor): """Set up a web server for moat bridge distribution. :type config: :class:`bridgedb.persistent.Conf` :param config: A configuration object from :mod:`bridgedb.main`. Currently, we use these options:: GIMP_CAPTCHA_DIR SERVER_PUBLIC_FQDN SUPPORTED_TRANSPORTS MOAT_DIST MOAT_DIST_VIA_MEEK_ONLY MOAT_TLS_CERT_FILE MOAT_TLS_KEY_FILE MOAT_SERVER_PUBLIC_ROOT MOAT_HTTPS_IP MOAT_HTTPS_PORT MOAT_HTTP_IP MOAT_HTTP_PORT MOAT_BRIDGES_PER_ANSWER MOAT_TRANSPORT_PREFERENCE_LIST MOAT_USE_IP_FROM_FORWARDED_HEADER MOAT_SKIP_LOOPBACK_ADDRESSES MOAT_ROTATION_PERIOD MOAT_GIMP_CAPTCHA_HMAC_KEYFILE MOAT_GIMP_CAPTCHA_RSA_KEYFILE :type distributor: :class:`bridgedb.distributors.moat.distributor.MoatDistributor` :param distributor: A bridge distributor. :raises SystemExit: if the servers cannot be started. :rtype: :api:`twisted.web.server.Site` :returns: A webserver. """ captcha = None fwdHeaders = config.MOAT_USE_IP_FROM_FORWARDED_HEADER numBridges = config.MOAT_BRIDGES_PER_ANSWER skipLoopback = config.MOAT_SKIP_LOOPBACK_ADDRESSES logging.info("Starting moat servers...") setFQDN(config.SERVER_PUBLIC_FQDN) setRoot(config.MOAT_SERVER_PUBLIC_ROOT) setSupportedTransports(config.SUPPORTED_TRANSPORTS) setPreferredTransports(config.MOAT_TRANSPORT_PREFERENCE_LIST) # Get the master HMAC secret key for CAPTCHA challenges, and then # create a new HMAC key from it for use on the server. captchaKey = crypto.getKey(config.MOAT_GIMP_CAPTCHA_HMAC_KEYFILE) hmacKey = crypto.getHMAC(captchaKey, "Moat-Captcha-Key") # Load or create our encryption keys: secretKey, publicKey = crypto.getRSAKey(config.MOAT_GIMP_CAPTCHA_RSA_KEYFILE) sched = Unscheduled() if config.MOAT_ROTATION_PERIOD: count, period = config.MOAT_ROTATION_PERIOD.split() sched = ScheduledInterval(count, period) sitePublicDir = getRoot() meek = CustomErrorHandlingResource() moat = CustomErrorHandlingResource() fetch = CaptchaFetchResource(hmacKey, publicKey, secretKey, config.GIMP_CAPTCHA_DIR, fwdHeaders, skipLoopback) check = CaptchaCheckResource(distributor, sched, numBridges, hmacKey, publicKey, secretKey, fwdHeaders, skipLoopback) moat.putChild("fetch", fetch) moat.putChild("check", check) meek.putChild("moat", moat) root = CustomErrorHandlingResource() root.putChild("meek", meek) root.putChild("moat", moat) site = Site(root) site.displayTracebacks = False if config.MOAT_HTTP_PORT: # pragma: no cover ip = config.MOAT_HTTP_IP or "" port = config.MOAT_HTTP_PORT or 80 try: reactor.listenTCP(port, site, interface=ip) except CannotListenError as error: raise SystemExit(error) logging.info("Started Moat HTTP server on %s:%d" % (str(ip), int(port))) if config.MOAT_HTTPS_PORT: # pragma: no cover ip = config.MOAT_HTTPS_IP or "" port = config.MOAT_HTTPS_PORT or 443 try: from twisted.internet.ssl import DefaultOpenSSLContextFactory factory = DefaultOpenSSLContextFactory(config.MOAT_TLS_KEY_FILE, config.MOAT_TLS_CERT_FILE) reactor.listenSSL(port, site, factory, interface=ip) except CannotListenError as error: raise SystemExit(error) logging.info("Started Moat TLS server on %s:%d" % (str(ip), int(port))) return site