Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/test_and_publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ jobs:
needs: test-installation
runs-on: ubuntu-22.04
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
permissions:
id-token: write
steps:
- name: Download distribution packages
uses: actions/download-artifact@v4
Expand All @@ -160,6 +162,4 @@ jobs:
- name: Build and publish to PyPI
uses: pypa/gh-action-pypi-publish@v1.13.0
with:
user: domain-connect
password: ${{ secrets.PYPI_PASSWORD }}
skip_existing: true
9 changes: 4 additions & 5 deletions domainconnectzone/DomainConnectImpl.py
Original file line number Diff line number Diff line change
Expand Up @@ -734,23 +734,22 @@ def process_records(template_records, zone_records, domain, host, params,
' host: ' + template_record['host'] +
' (from ' + orig_host + ')')
if template_record_type in ['A', 'AAAA', 'MX', 'NS', 'REDIR301', 'REDIR302']:
if not is_valid_host_other(template_record['host'],
False):
if not is_valid_host_other(template_record['host']):
raise InvalidData(err_msg)
elif template_record_type in ['SPFM']:
if not is_valid_host_other(template_record['host'], False):
if not is_valid_host_other(template_record['host']):
raise InvalidData(err_msg)

elif template_record_type in ['TXT']:
if not is_valid_host_other(template_record['host'], True):
if not is_valid_host_other(template_record['host']):
raise InvalidData(err_msg)

elif template_record_type in ['CNAME', 'NS']:
if not is_valid_host_cname_or_ns(template_record['host']):
raise InvalidData(err_msg)

elif is_custom:
if not is_valid_host_other(template_record['host'], True):
if not is_valid_host_other(template_record['host']):
raise InvalidData(err_msg)

# Points To / Target
Expand Down
20 changes: 10 additions & 10 deletions domainconnectzone/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ def is_valid_pointsTo_host(hostname):
return False
if len(hostname) >= 1 and hostname[-1] == ".":
hostname = hostname[:-1] # strip exactly one dot from the right, if present
allowed = re.compile(r"(?!-)_?[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
allowed = re.compile(r"(?!-)[A-Z\d_-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in hostname.split("."))

def is_valid_host_other(input, allow_underscores):
def is_valid_host_other(input):
if not input or input == '@' or input == '':
return True

if len(input) > 253:
return False

allowed = re.compile(r"(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x.lstrip('_')) if allow_underscores else allowed.match(x) for x in input.split("."))
allowed = re.compile(r"(?!-)[A-Z\d_-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in input.split("."))


def is_valid_host_cname_or_ns(input):
Expand All @@ -48,23 +48,23 @@ def is_valid_host_cname_or_ns(input):
if len(input) > 253:
return False

allowed = re.compile(r"(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x.lstrip('_')) for x in input.split(".")) #allows for leading underscores
allowed = re.compile(r"(?!-)[A-Z\d_-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in input.split("."))


def is_valid_host_srv(input):
if len(input) > 253:
return False

allowed = re.compile(r"(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x.lstrip('_')) for x in input.split(".")) #allows for leading underscores
allowed = re.compile(r"(?!-)[A-Z\d_-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in input.split("."))


def is_valid_name_srv(input):
if input == "@":
return True # APEX is allowed as a name in SRV
allowed = re.compile(r"(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x.lstrip('_')) for x in input.split(".")) #allows for leading underscores
allowed = re.compile(r"(?!-)[A-Z\d_-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in input.split("."))


def is_valid_target_redir(input):
Expand Down
234 changes: 231 additions & 3 deletions test/test_definitions/process_records_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1646,8 +1646,8 @@ tests:
expect:
exception: InvalidTemplate

- id: exception_spfm_underscore_host
description: "SPFM with leading-underscore host raises InvalidData"
- id: spfm_underscore_host
description: "SPFM with leading-underscore host is allowed"
input:
zone_records: []
template_records:
Expand All @@ -1656,7 +1656,210 @@ tests:
host: ""
params: {}
expect:
exception: InvalidData
new_count: 1
delete_count: 0
records:
- {type: TXT, name: "_underscore", data: "v=spf1 foo ~all", ttl: 6000}

# ---------------------------------------------------------------------------
# Underscore in host — all core record types
# ---------------------------------------------------------------------------
- id: a_underscore_leading_host
description: "A record with leading underscore in host is allowed"
input:
zone_records: []
template_records:
- {type: A, host: "_verify", pointsTo: 1.2.3.4, ttl: 300}
domain: foo.com
host: ""
params: {}
expect:
new_count: 1
delete_count: 0
records:
- {type: A, name: "_verify", data: 1.2.3.4, ttl: 300}

- id: a_underscore_middle_host
description: "A record with underscore in the middle of host is allowed"
input:
zone_records: []
template_records:
- {type: A, host: "tinkermail_verify", pointsTo: 1.2.3.4, ttl: 300}
domain: foo.com
host: ""
params: {}
expect:
new_count: 1
delete_count: 0
records:
- {type: A, name: "tinkermail_verify", data: 1.2.3.4, ttl: 300}

- id: aaaa_underscore_leading_host
description: "AAAA record with leading underscore in host is allowed"
input:
zone_records: []
template_records:
- {type: AAAA, host: "_verify", pointsTo: "::1", ttl: 300}
domain: foo.com
host: ""
params: {}
expect:
new_count: 1
delete_count: 0
records:
- {type: AAAA, name: "_verify", data: "::1", ttl: 300}

- id: aaaa_underscore_middle_host
description: "AAAA record with underscore in the middle of host is allowed"
input:
zone_records: []
template_records:
- {type: AAAA, host: "tinkermail_verify", pointsTo: "::1", ttl: 300}
domain: foo.com
host: ""
params: {}
expect:
new_count: 1
delete_count: 0
records:
- {type: AAAA, name: "tinkermail_verify", data: "::1", ttl: 300}

- id: mx_underscore_leading_host
description: "MX record with leading underscore in host is allowed"
input:
zone_records: []
template_records:
- {type: MX, host: "_mail", pointsTo: mx.example.com, ttl: 300, priority: 10}
domain: foo.com
host: ""
params: {}
expect:
new_count: 1
delete_count: 0
records:
- {type: MX, name: "_mail", data: mx.example.com, ttl: 300, priority: 10}

- id: mx_underscore_middle_host
description: "MX record with underscore in the middle of host is allowed"
input:
zone_records: []
template_records:
- {type: MX, host: "sub_domain", pointsTo: mx.example.com, ttl: 300, priority: 10}
domain: foo.com
host: ""
params: {}
expect:
new_count: 1
delete_count: 0
records:
- {type: MX, name: "sub_domain", data: mx.example.com, ttl: 300, priority: 10}

- id: cname_underscore_leading_host
description: "CNAME record with leading underscore in host is allowed"
input:
zone_records: []
template_records:
- {type: CNAME, host: "_verify", pointsTo: target.example.com, ttl: 300}
domain: foo.com
host: ""
params: {}
expect:
new_count: 1
delete_count: 0
records:
- {type: CNAME, name: "_verify", data: target.example.com, ttl: 300}

- id: cname_underscore_middle_host
description: "CNAME record with underscore in the middle of host is allowed"
input:
zone_records: []
template_records:
- {type: CNAME, host: "tinkermail_verify", pointsTo: target.example.com, ttl: 300}
domain: foo.com
host: ""
params: {}
expect:
new_count: 1
delete_count: 0
records:
- {type: CNAME, name: "tinkermail_verify", data: target.example.com, ttl: 300}

- id: ns_underscore_leading_host
description: "NS record with leading underscore in host is allowed"
input:
zone_records: []
template_records:
- {type: NS, host: "_sub", pointsTo: ns.example.com, ttl: 300}
domain: foo.com
host: ""
params: {}
expect:
new_count: 1
delete_count: 0
records:
- {type: NS, name: "_sub", data: ns.example.com, ttl: 300}

- id: ns_underscore_middle_host
description: "NS record with underscore in the middle of host is allowed"
input:
zone_records: []
template_records:
- {type: NS, host: "sub_zone", pointsTo: ns.example.com, ttl: 300}
domain: foo.com
host: ""
params: {}
expect:
new_count: 1
delete_count: 0
records:
- {type: NS, name: "sub_zone", data: ns.example.com, ttl: 300}

- id: txt_underscore_middle_host
description: "TXT record with underscore in the middle of host is allowed"
input:
zone_records: []
template_records:
- {type: TXT, host: "tinkermail_verify", data: somevalue, ttl: 300}
domain: foo.com
host: ""
params: {}
expect:
new_count: 1
delete_count: 0
records:
- {type: TXT, name: "tinkermail_verify", data: somevalue, ttl: 300}

- id: spfm_underscore_middle_host
description: "SPFM with underscore in the middle of host is allowed"
input:
zone_records: []
template_records:
- {type: SPFM, host: "mail_sub", spfRules: foo}
domain: foo.com
host: ""
params: {}
expect:
new_count: 1
delete_count: 0
records:
- {type: TXT, name: "mail_sub", data: "v=spf1 foo ~all", ttl: 6000}

- id: srv_underscore_middle_name
description: "SRV record with underscore in the middle of name is allowed"
input:
zone_records: []
template_records:
- {type: SRV, name: "_sip_old", target: "127.0.0.1", protocol: UDP, service: foo.com,
priority: 10, weight: 10, port: 5, ttl: 400}
domain: foo.com
host: bar
params: {}
expect:
new_count: 1
delete_count: 0
records:
- {type: SRV, name: "_sip_old.bar", data: "127.0.0.1", protocol: UDP, service: foo.com,
priority: 10, weight: 10, port: 5, ttl: 400}

- id: exception_txt_host_with_space
description: "TXT with a host containing a space raises InvalidData"
Expand Down Expand Up @@ -1826,3 +2029,28 @@ tests:
params: {}
expect:
exception: InvalidData

- id: exception_spfm_invalid_host
description: "SPFM with an invalid host (hyphen-leading label) raises InvalidData"
input:
zone_records: []
template_records:
- {type: SPFM, host: "-invalid", spfRules: foo}
domain: foo.com
host: ""
params: {}
expect:
exception: InvalidData

- id: NS_conflict_itself_a_before_ns
description: "NS conflicts with A already added to new records (A first, NS second)"
input:
zone_records: []
template_records:
- {type: A, host: "%sub%", pointsTo: 192.168.1.1, ttl: 600}
- {type: NS, host: "%sub%", pointsTo: ns.example.com, ttl: 600}
domain: foo.com
host: ""
params: {sub: blah}
expect:
exception: InvalidData