Missing a repository? Have a look at https://code.cacert.org/.

summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorJan Dittberner <jandd@cacert.org>2016-05-07 13:37:12 +0200
committerJan Dittberner <jandd@cacert.org>2016-05-07 13:37:12 +0200
commit2fc2c4a3c1b24612d8837e0f293a6637c80696e5 (patch)
treeb055155e93a777df0edff429558a17cf37ae6b87 /docs
parentff88c389a76d7795d931d5c4f8f778876830133b (diff)
downloadcacert-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.py40
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):