Skip to content

Commit

Permalink
Add --must-staple flag.
Browse files Browse the repository at this point in the history
  • Loading branch information
jsha committed Mar 16, 2016
1 parent 8985c46 commit 09a38c7
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 6 deletions.
3 changes: 3 additions & 0 deletions letsencrypt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1589,6 +1589,9 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False):
helpful.add(
"security", "--rsa-key-size", type=int, metavar="N",
default=flag_default("rsa_key_size"), help=config_help("rsa_key_size"))
helpful.add(
"security", "--must-staple", action="store_true",
help=config_help("must_staple"), dest="must_staple", default=False)
helpful.add(
"security", "--redirect", action="store_true",
help="Automatically redirect all HTTP traffic to HTTPS for the newly "
Expand Down
20 changes: 14 additions & 6 deletions letsencrypt/crypto_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,11 @@ def init_save_csr(privkey, names, path, csrname="csr-letsencrypt.pem"):
:rtype: :class:`letsencrypt.le_util.CSR`
"""
csr_pem, csr_der = make_csr(privkey.pem, names)

config = zope.component.getUtility(interfaces.IConfig)

csr_pem, csr_der = make_csr(privkey.pem, names,
must_staple=config.must_staple)

# Save CSR
le_util.make_or_verify_dir(path, 0o755, os.geteuid(),
config.strict_permissions)
Expand All @@ -92,7 +94,7 @@ def init_save_csr(privkey, names, path, csrname="csr-letsencrypt.pem"):


# Lower level functions
def make_csr(key_str, domains):
def make_csr(key_str, domains, must_staple=False):
"""Generate a CSR.
:param str key_str: PEM-encoded RSA key.
Expand All @@ -111,13 +113,19 @@ def make_csr(key_str, domains):
req.get_subject().CN = domains[0]
# TODO: what to put into req.get_subject()?
# TODO: put SAN if len(domains) > 1
req.add_extensions([
extensions = [
OpenSSL.crypto.X509Extension(
"subjectAltName",
critical=False,
value=", ".join("DNS:%s" % d for d in domains)
),
])
)
]
if must_staple:
extensions.append(OpenSSL.crypto.X509Extension(
"1.3.6.1.5.5.7.1.24",
critical=False,
value="DER:30:03:02:01:05"))
req.add_extensions(extensions)
req.set_version(2)
req.set_pubkey(pkey)
req.sign(pkey, "sha256")
Expand Down
2 changes: 2 additions & 0 deletions letsencrypt/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ class IConfig(zope.interface.Interface):
email = zope.interface.Attribute(
"Email used for registration and recovery contact.")
rsa_key_size = zope.interface.Attribute("Size of the RSA key.")
must_staple = zope.interface.Attribute(
"Whether to request the OCSP Must Staple extension.")

config_dir = zope.interface.Attribute("Configuration directory.")
work_dir = zope.interface.Attribute("Working directory.")
Expand Down
19 changes: 19 additions & 0 deletions letsencrypt/tests/crypto_util_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,25 @@ def test_san(self):
['example.com', 'www.example.com'], get_sans_from_csr(
csr_der, OpenSSL.crypto.FILETYPE_ASN1))

def test_must_staple(self):
# TODO: Fails for RSA256_KEY
csr_pem, _ = self._call(
RSA512_KEY, ['example.com', 'www.example.com'], must_staple=True)
csr = OpenSSL.crypto.load_certificate_request(
OpenSSL.crypto.FILETYPE_PEM, csr_pem)

# In pyopenssl 0.13 (used with TOXENV=py26-oldest and py27-oldest), csr
# objects don't have a get_extensions() method, so we skip this test if
# the method isn't available.
if csr.get_extensions:
# NOTE: Ideally we would filter by the TLS Feature OID, but
# OpenSSL.crypto.X509Extension doesn't give us the extension's raw OID,
# and the shortname field is just "UNDEF"
must_staple_exts = [e for e in csr.get_extensions()
if e.get_data() == "0\x03\x02\x01\x05"]
self.assertEqual(len(must_staple_exts), 1,
"Expected exactly one Must Staple extension")


class ValidCSRTest(unittest.TestCase):
"""Tests for letsencrypt.crypto_util.valid_csr."""
Expand Down

0 comments on commit 09a38c7

Please sign in to comment.