mirror of
https://github.com/certbot/certbot.git
synced 2026-08-01 19:02:52 +02:00
database-backed blacklisting of moduli and names
This commit is contained in:
+20
-5
@@ -11,8 +11,12 @@ import M2Crypto
|
|||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
assert LooseVersion(M2Crypto.version) >= LooseVersion("0.22")
|
assert LooseVersion(M2Crypto.version) >= LooseVersion("0.22")
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import blacklists
|
||||||
# we can use temp() to get tempfiles to pass to OpenSSL subprocesses.
|
# we can use temp() to get tempfiles to pass to OpenSSL subprocesses.
|
||||||
|
|
||||||
|
forbidden_moduli = blacklists.forbidden_moduli()
|
||||||
|
forbidden_names = blacklists.forbidden_names()
|
||||||
|
|
||||||
def parse(csr):
|
def parse(csr):
|
||||||
"""
|
"""
|
||||||
Is this CSR syntactically valid? (TODO: remove)
|
Is this CSR syntactically valid? (TODO: remove)
|
||||||
@@ -41,11 +45,23 @@ def goodkey(key):
|
|||||||
"""Does this public key comply with our CA policy?"""
|
"""Does this public key comply with our CA policy?"""
|
||||||
key = str(key)
|
key = str(key)
|
||||||
bits = modulusbits(key)
|
bits = modulusbits(key)
|
||||||
if bits and bits >= 2000:
|
if bits and bits >= 2000 and not blacklisted(key):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def blacklisted(key):
|
||||||
|
"""Is this key blacklisted?"""
|
||||||
|
# There is also a modulus function that uses M2Crypto.m2.rsa_get_n
|
||||||
|
# instead of EVP.PKey, but it seems to erroneously prepend the exponent
|
||||||
|
# to the modulus or something.
|
||||||
|
bio = M2Crypto.BIO.MemoryBuffer(key)
|
||||||
|
pubkey = M2Crypto.RSA.load_pub_key_bio(bio)
|
||||||
|
pkey = M2Crypto.EVP.PKey()
|
||||||
|
pkey.assign_rsa(pubkey)
|
||||||
|
modulus = pkey.get_modulus()
|
||||||
|
return modulus in forbidden_moduli
|
||||||
|
|
||||||
def csr_goodkey(csr):
|
def csr_goodkey(csr):
|
||||||
"""Does this CSR's embedded public key comply with our CA policy?"""
|
"""Does this CSR's embedded public key comply with our CA policy?"""
|
||||||
csr = str(csr)
|
csr = str(csr)
|
||||||
@@ -138,9 +154,8 @@ def can_sign(name):
|
|||||||
# the name is actually a FQDN.
|
# the name is actually a FQDN.
|
||||||
name = str(name)
|
name = str(name)
|
||||||
if "." not in name: return False
|
if "." not in name: return False
|
||||||
# Examples of names that are forbidden by policy due to a blacklist.
|
# Names that are forbidden by policy due to a blacklist.
|
||||||
if name in ["google.com", "www.google.com"]: return False
|
return name not in forbidden_names
|
||||||
return True
|
|
||||||
|
|
||||||
def verify(key, data, signature):
|
def verify(key, data, signature):
|
||||||
"""
|
"""
|
||||||
@@ -209,7 +224,7 @@ def issue(csr, subjects):
|
|||||||
"""Issue a certificate requested by CSR, specifying the subject names
|
"""Issue a certificate requested by CSR, specifying the subject names
|
||||||
indicated in subjects, and return the certificate. Calls to this
|
indicated in subjects, and return the certificate. Calls to this
|
||||||
function should be guarded with a lock to ensure that the calls never
|
function should be guarded with a lock to ensure that the calls never
|
||||||
overlapping calls."""
|
overlap."""
|
||||||
if not subjects:
|
if not subjects:
|
||||||
return None
|
return None
|
||||||
csr = str(csr)
|
csr = str(csr)
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import redis
|
||||||
|
|
||||||
|
r = redis.Redis()
|
||||||
|
|
||||||
|
# Moduli should be stored in Redis in hexadecimal, all uppercase. If these
|
||||||
|
# sets don't exist, sismember returns False (not an exception).
|
||||||
|
|
||||||
|
class forbidden_moduli(object):
|
||||||
|
def __contains__(self, modulus):
|
||||||
|
return r.sismember("debian_moduli", modulus) or r.sismember("factorable_moduli", modulus)
|
||||||
|
|
||||||
|
class forbidden_names(object):
|
||||||
|
def __contains__(self, name):
|
||||||
|
return r.sismember("forbidden_names", name)
|
||||||
Reference in New Issue
Block a user