Merge pull request #1163 from AdvanticGmbH/idna_decode

fix: use idna module to support extended character set
This commit is contained in:
jbe-dw 2022-06-17 15:47:55 +02:00 committed by GitHub
commit 2a75013de4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 26 additions and 7 deletions

View File

@ -4,6 +4,7 @@ import json
import requests import requests
import hashlib import hashlib
import ipaddress import ipaddress
import idna
from collections.abc import Iterable from collections.abc import Iterable
from distutils.version import StrictVersion from distutils.version import StrictVersion
@ -248,10 +249,27 @@ def pretty_domain_name(value):
if value.startswith('xn--') \ if value.startswith('xn--') \
or value.find('.xn--') != -1: or value.find('.xn--') != -1:
try: try:
return value.encode().decode('idna') return to_idna(value, 'decode')
except: except:
raise Exception("Cannot decode IDN domain") raise Exception('Cannot decode IDN domain')
else: else:
return value return value
else: else:
raise Exception("Require the Punycode in string format") raise Exception('Require the Punycode in string format')
def to_idna(value, action):
splits = value.split()
result = []
if action == 'encode':
for split in splits:
try:
# Try encoding to idna
result.append(idna.encode(split).decode())
except idna.IDNAError:
result.append(split)
elif action == 'decode':
for split in splits:
result.append(idna.decode(split))
else:
raise Exception('No valid action received')
return ' '.join(result)

View File

@ -169,12 +169,12 @@ class Record(object):
record['record_data'] = record['record_data'].replace('[ZONE]', domain_name) record['record_data'] = record['record_data'].replace('[ZONE]', domain_name)
# Translate record name into punycode (IDN) as that's the only way # Translate record name into punycode (IDN) as that's the only way
# to convey non-ascii records to the dns server # to convey non-ascii records to the dns server
record['record_name'] = record['record_name'].encode('idna').decode() record['record_name'] = utils.to_idna(record["record_name"], "encode")
#TODO: error handling #TODO: error handling
# If the record is an alias (CNAME), we will also make sure that # If the record is an alias (CNAME), we will also make sure that
# the target domain is properly converted to punycode (IDN) # the target domain is properly converted to punycode (IDN)
if record["record_type"] == 'CNAME': if record['record_type'] == 'CNAME' or record['record_type'] == 'SOA':
record['record_data'] = record['record_data'].encode('idna').decode() record['record_data'] = utils.to_idna(record['record_data'], 'encode')
#TODO: error handling #TODO: error handling
# If it is ipv6 reverse zone and PRETTY_IPV6_PTR is enabled, # If it is ipv6 reverse zone and PRETTY_IPV6_PTR is enabled,
# We convert ipv6 address back to reverse record format # We convert ipv6 address back to reverse record format

View File

@ -10,6 +10,7 @@ from flask_login import login_required, current_user, login_manager
from ..lib.utils import pretty_domain_name from ..lib.utils import pretty_domain_name
from ..lib.utils import pretty_json from ..lib.utils import pretty_json
from ..lib.utils import to_idna
from ..decorators import can_create_domain, operator_role_required, can_access_domain, can_configure_dnssec, can_remove_domain from ..decorators import can_create_domain, operator_role_required, can_access_domain, can_configure_dnssec, can_remove_domain
from ..models.user import User, Anonymous from ..models.user import User, Anonymous
from ..models.account import Account from ..models.account import Account
@ -379,7 +380,7 @@ def add():
# Encode domain name into punycode (IDN) # Encode domain name into punycode (IDN)
try: try:
domain_name = domain_name.encode('idna').decode() domain_name = to_idna(domain_name, 'encode')
except: except:
current_app.logger.error("Cannot encode the domain name {}".format(domain_name)) current_app.logger.error("Cannot encode the domain name {}".format(domain_name))
current_app.logger.debug(traceback.format_exc()) current_app.logger.debug(traceback.format_exc())