Add option to ignore compromised certificates
This would allow to stop spam attacks without pausing sites that allow compromised certificates and without action from site owners. However, without mass adoption of adding individual permissions on sites for valid users of such certificates, this will also block updates from such users. In any case this is more of a temporary measure in case we face such an attack before the whole user id issue is resolved
This commit is contained in:
parent
ee0829d95e
commit
31d94a16b6
3 changed files with 43 additions and 5 deletions
|
@ -297,6 +297,8 @@ class Config(object):
|
|||
|
||||
self.parser.add_argument('--download-optional', choices=["manual", "auto"], default="manual")
|
||||
|
||||
self.parser.add_argument('--lax-cert-check', action=argparse.BooleanOptionalAction, default=True, help="Enabling lax cert check allows users getting site writing priviledges by employing compromized (i.e. with leaked private keys) cert issuer. Disable for spam protection")
|
||||
|
||||
self.parser.add_argument('--tor', help='enable: Use only for Tor peers, always: Use Tor for every connection', choices=["disable", "enable", "always"], default='enable')
|
||||
self.parser.add_argument('--tor-controller', help='Tor controller address', metavar='ip:port', default='127.0.0.1:9051')
|
||||
self.parser.add_argument('--tor-proxy', help='Tor proxy address', metavar='ip:port', default='127.0.0.1:9050')
|
||||
|
|
|
@ -29,7 +29,17 @@ class SignError(Exception):
|
|||
|
||||
|
||||
@PluginManager.acceptPlugins
|
||||
class ContentManager(object):
|
||||
class ContentManager:
|
||||
"""Manage site content verifying and other related stuff"""
|
||||
|
||||
def loadBadCerts():
|
||||
try:
|
||||
with open(f'{config.data_dir}/badcerts.json') as f:
|
||||
return set(json.load(f))
|
||||
except FileNotFoundError:
|
||||
return set()
|
||||
|
||||
bad_certs = loadBadCerts()
|
||||
|
||||
def __init__(self, site):
|
||||
self.site = site
|
||||
|
@ -38,6 +48,13 @@ class ContentManager(object):
|
|||
self.hashfield = PeerHashfield()
|
||||
self.has_optional_files = False
|
||||
|
||||
def addBadCert(self, sign):
|
||||
addr = CryptBitcoin.get_sign_address_64('compromised', sign)
|
||||
if addr:
|
||||
self.bad_certs.add(addr)
|
||||
with open(f'{config.data_dir}/badcerts.json', 'w') as f:
|
||||
json.dump(list(self.bad_certs), f)
|
||||
|
||||
# Load all content.json files
|
||||
def loadContents(self):
|
||||
if len(self.contents) == 0:
|
||||
|
@ -478,6 +495,9 @@ class ContentManager(object):
|
|||
return self.getUserContentRules(parent_content, inner_path, content)
|
||||
return False
|
||||
|
||||
def isGoodCert(self, cert):
|
||||
return cert not in self.bad_certs
|
||||
|
||||
# Get rules for a user file
|
||||
# Return: The rules of the file or False if not allowed
|
||||
def getUserContentRules(self, parent_content, inner_path, content):
|
||||
|
@ -511,7 +531,20 @@ class ContentManager(object):
|
|||
banned = False
|
||||
if "signers" in rules:
|
||||
rules["signers"] = rules["signers"][:] # Make copy of the signers
|
||||
for permission_pattern, permission_rules in list(user_contents["permission_rules"].items()): # Regexp rules
|
||||
|
||||
if content is not None:
|
||||
name, domain = content['cert_user_id'].rsplit('@', 1)
|
||||
cert_addresses = parent_content['user_contents']['cert_signers'].get(domain)
|
||||
else:
|
||||
cert_addresses = None
|
||||
# to prevent spam, if cert is compromised, only allow personal rules
|
||||
if config.lax_cert_check or cert_addresses is None or self.isGoodCert(cert_addresses[0]):
|
||||
permission_rules = user_contents.get('permission_rules', {}).items()
|
||||
if not self.isGoodCert(cert_addresses[0]):
|
||||
self.log.warning('Accepting compromised certificate! This may lead to spam attack. Turn off with --no_lax_cert_check. Default behaviour may change in the future.')
|
||||
else:
|
||||
permission_rules = {}
|
||||
for permission_pattern, permission_rules in permission_rules: # Regexp rules
|
||||
if not SafeRe.match(permission_pattern, user_urn):
|
||||
continue # Rule is not valid for user
|
||||
if permission_rules is None:
|
||||
|
@ -892,9 +925,9 @@ class ContentManager(object):
|
|||
raise VerifyError("No rules")
|
||||
|
||||
# Check include size limit
|
||||
if rules.get("max_size") is not None: # Include size limit
|
||||
if content_size > rules["max_size"]:
|
||||
raise VerifyError("Include too large %sB > %sB" % (content_size, rules["max_size"]))
|
||||
max_size = rules.get("max_size", 0)
|
||||
if content_size > max_size:
|
||||
raise VerifyError(f'Include too large {content_size}B > {max_size}B')
|
||||
|
||||
if rules.get("max_size_optional") is not None: # Include optional files limit
|
||||
if content_size_optional > rules["max_size_optional"]:
|
||||
|
|
|
@ -405,6 +405,9 @@ class UiWebsocket(object):
|
|||
def actionSiteBadFiles(self, to):
|
||||
return list(self.site.bad_files.keys())
|
||||
|
||||
def actionBadCert(self, to, sign):
|
||||
self.site.content_manager.addBadCert(sign)
|
||||
|
||||
# Join to an event channel
|
||||
def actionChannelJoin(self, to, channels):
|
||||
if type(channels) != list:
|
||||
|
|
Loading…
Reference in a new issue