diff --git a/README.md b/README.md index 00100c4..e245dc5 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Optional packages * PyYAML (when using config files in YAML format) * dnspython (required for the dns.nsupdate mode) + * idna (for automatically translating to the IDNA representation of unicode domain names) Initial Setup ------------- diff --git a/acertmgr/configuration.py b/acertmgr/configuration.py index 61fd191..9d16959 100644 --- a/acertmgr/configuration.py +++ b/acertmgr/configuration.py @@ -11,6 +11,7 @@ import copy import hashlib import io import os +import json # Backward compatiblity for older versions/installations of acertmgr LEGACY_WORK_DIR = "/etc/acme" @@ -62,6 +63,29 @@ def parse_config_entry(entry, globalconfig, work_dir, authority_tos_agreement): config['domainlist'] = config['domains'].split(' ') config['id'] = hashlib.md5(config['domains'].encode('utf-8')).hexdigest() + # Append IDNA domains to the domainlist and domains + if any(ord(c) >= 128 for c in config['domains']): + try: + import idna + domainlist = [] + config['domaintranslation'] = {} + for domain in config['domainlist']: + if any(ord(c) >= 128 for c in domain): + # Translate IDNA domain name from a unicode domain (handle wildcards separately) + if domain.startswith('*.'): + idna_domain = "*.{}".format(idna.encode(domain[2:]).decode('utf-8')) + else: + idna_domain = idna.encode(domain).decode('utf-8') + domainlist.append(idna_domain) + config['domaintranslation'][idna_domain] = domain + else: + domainlist.append(domain) + # Refresh the domainlist and domains config value + config['domainlist'] = domainlist + config['domains'] = ' '.join(domainlist) + except ImportError: + print("Unicode domain found but IDNA names could not be translated due to missing idna module") + # Action config defaults config['defaults'] = globalconfig.get('defaults', {}) @@ -129,8 +153,9 @@ def parse_config_entry(entry, globalconfig, work_dir, authority_tos_agreement): if len(genericfgs) > 0: cfg.update(genericfgs[0]) - # Update handler config with more specific values - specificcfgs = [x for x in handlerconfigs if ('domain' in x and x['domain'] == domain)] + # Update handler config with more specific values (use original names for translated unicode domains) + _domain = config.get('domaintranslation', {}).get(domain, domain) + specificcfgs = [x for x in handlerconfigs if 'domain' in x and x['domain'] == _domain] if len(specificcfgs) > 0: cfg.update(specificcfgs[0]) @@ -191,7 +216,6 @@ def load(): if os.path.isfile(global_config_file): with io.open(global_config_file) as config_fd: try: - import json globalconfig = json.load(config_fd) except ValueError: import yaml @@ -212,7 +236,6 @@ def load(): os.path.abspath(domain_config_file) != os.path.abspath(global_config_file): with io.open(domain_config_file) as config_fd: try: - import json for entry in json.load(config_fd).items(): config.append(parse_config_entry(entry, globalconfig, work_dir, authority_tos_agreement)) except ValueError: diff --git a/docs/archlinux/python-acertmgr/PKGBUILD b/docs/archlinux/python-acertmgr/PKGBUILD index 83df427..572bf81 100644 --- a/docs/archlinux/python-acertmgr/PKGBUILD +++ b/docs/archlinux/python-acertmgr/PKGBUILD @@ -8,6 +8,7 @@ url='https://github.com/moepman/acertmgr' license=('ISC') depends=('python-cryptography') optdepends=('yaml: python-yaml' + 'idna: python-idna' 'dns.nsupdate: python-dnspython') makedepends=('git') conflicts=('python-acertmgr') diff --git a/docs/archlinux/python2-acertmgr/PKGBUILD b/docs/archlinux/python2-acertmgr/PKGBUILD index b45f0d2..a56e77c 100644 --- a/docs/archlinux/python2-acertmgr/PKGBUILD +++ b/docs/archlinux/python2-acertmgr/PKGBUILD @@ -8,6 +8,7 @@ url='https://github.com/moepman/acertmgr' license=('ISC') depends=('python2-cryptography') optdepends=('yaml: python2-yaml' + 'idna: python2-idna' 'dns.nsupdate: python2-dnspython') makedepends=('git') conflicts=('python-acertmgr') diff --git a/setup.py b/setup.py index dc7ba1e..4b216c3 100644 --- a/setup.py +++ b/setup.py @@ -60,6 +60,9 @@ setup( "yaml": [ "yaml", ], + "idna": [ + "idna", + ], }, entry_points={ 'console_scripts': [