diff options
author | Jan Dittberner <jandd@cacert.org> | 2016-05-07 13:37:12 +0200 |
---|---|---|
committer | Jan Dittberner <jandd@cacert.org> | 2016-05-07 13:37:12 +0200 |
commit | 2fc2c4a3c1b24612d8837e0f293a6637c80696e5 (patch) | |
tree | b055155e93a777df0edff429558a17cf37ae6b87 /docs | |
parent | ff88c389a76d7795d931d5c4f8f778876830133b (diff) | |
download | cacert-infradocs-2fc2c4a3c1b24612d8837e0f293a6637c80696e5.tar.gz cacert-infradocs-2fc2c4a3c1b24612d8837e0f293a6637c80696e5.tar.xz cacert-infradocs-2fc2c4a3c1b24612d8837e0f293a6637c80696e5.zip |
Add subject alternative name validation
This commit adds validation of subject alternative names. Currently SANs
of type DNS, EMAIL and IP are supported. The rendering has been modified
to not output type information. All validation should work in offline
mode.
Diffstat (limited to 'docs')
-rw-r--r-- | docs/sphinxext/cacert.py | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/docs/sphinxext/cacert.py b/docs/sphinxext/cacert.py index 1dd731a..bde161f 100644 --- a/docs/sphinxext/cacert.py +++ b/docs/sphinxext/cacert.py @@ -9,6 +9,7 @@ __version__ = '0.1.0' import re +from ipaddress import ip_address from docutils import nodes from docutils.parsers.rst import Directive @@ -20,6 +21,7 @@ from sphinx.errors import SphinxError from sphinx.util.nodes import set_source_info, make_refnode from dateutil.parser import parse as date_parse +from validate_email import validate_email class sslcert_node(nodes.General, nodes.Element): @@ -51,9 +53,39 @@ def create_table_row(rowdata): return row +def is_valid_hostname(hostname): + if len(hostname) > 255: + return False + if hostname[-1] == ".": # strip exactly one dot from the right, if present + hostname = hostname[:-1] + allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE) + return all(allowed.match(x) for x in hostname.split(".")) + + +def is_valid_ipaddress(content): + try: + ip_address(content) + except ValueError: + return False + return True + + def subject_alternative_names(argument): - value = [san.strip() for san in argument.split(',')] - # TODO: sanity checks for SANs + value = [san.strip().split(':', 1) for san in argument.split(',')] + for typ, content in value: + if typ == 'DNS': + if not is_valid_hostname(content): + raise ValueError("%s is no valid DNS name" % content) + elif typ == 'EMAIL': + if not validate_email(content): + raise ValueError("%s is not a valid email address" % content) + elif typ == 'IP': + if not is_valid_ipaddress(content): + raise ValueError("%s is not a valid IP address" % content) + else: + raise ValueError( + "handling of %s subject alternative names (%s) has not been " + "implemented" % (typ, content)) return value @@ -237,7 +269,9 @@ def _build_cert_anchor_name(cn, serial): def _format_subject_alternative_names(altnames): - return nodes.paragraph(text = ", ".join(altnames)) + return nodes.paragraph(text = ", ".join([ + content for _, content in altnames + ])) def _place_sort_key(place): |