Check TXT/SPF records for RFC1035 sec. 5.1
If record data has empty spaces it should be surrounded by double quotes. This patch will raise an error during validation if record has whitespaces, empty spaces, tabs, etc., but not wrapped in " " (double quotes). Corresponding RFC part: <character-string> is expressed in one or two ways: as a contiguous set of characters without interior spaces, or as a string beginning with a " and ending with a ". Inside a " delimited string any character can occur, except for a " itself, which must be quoted using \ (back slash). Closes-Bug: 1755788 Depends-On: https://review.openstack.org/#/c/617809/ Change-Id: I159d0732688ddf1337ab3602a84a43fd043dcaa2
This commit is contained in:
parent
59d8cab9bb
commit
02ef0350af
@ -187,10 +187,8 @@ class RecordSet(base.DesignateObject, base.DictObjectMixin,
|
||||
error_indexes.append(i)
|
||||
|
||||
except Exception as e:
|
||||
error_message = str.format(
|
||||
'Provided object is not valid. '
|
||||
'Got a %s error with message %s' %
|
||||
(type(e).__name__, six.text_type(e)))
|
||||
error_message = ('Provided object is not valid. Got a %s error'
|
||||
' with message %s' % (type(e).__name__, six.text_type(e)))
|
||||
raise exceptions.InvalidObject(error_message)
|
||||
|
||||
else:
|
||||
|
@ -16,6 +16,7 @@ from designate.objects.record import Record
|
||||
from designate.objects.record import RecordList
|
||||
from designate.objects import base
|
||||
from designate.objects import fields
|
||||
from designate.exceptions import InvalidObject
|
||||
|
||||
|
||||
@base.DesignateRegistry.register
|
||||
@ -32,6 +33,23 @@ class SPF(Record):
|
||||
return self.txt_data
|
||||
|
||||
def _from_string(self, value):
|
||||
if (not value.startswith('"') and not value.endswith('"')):
|
||||
# value with spaces should be quoted as per RFC1035 5.1
|
||||
for element in value:
|
||||
if element.isspace():
|
||||
err = ("Empty spaces are not allowed in SPF record, "
|
||||
"unless wrapped in double quotes.")
|
||||
raise InvalidObject(err)
|
||||
else:
|
||||
# quotes within value should be escaped with backslash
|
||||
strip_value = value.strip('"')
|
||||
for index, char in enumerate(strip_value):
|
||||
if char == '"':
|
||||
if strip_value[index - 1] != "\\":
|
||||
err = ("Quotation marks should be escaped with "
|
||||
"backslash.")
|
||||
raise InvalidObject(err)
|
||||
|
||||
self.txt_data = value
|
||||
|
||||
# The record type is defined in the RFC. This will be used when the record
|
||||
|
@ -16,6 +16,7 @@ from designate.objects.record import Record
|
||||
from designate.objects.record import RecordList
|
||||
from designate.objects import base
|
||||
from designate.objects import fields
|
||||
from designate.exceptions import InvalidObject
|
||||
|
||||
|
||||
@base.DesignateRegistry.register
|
||||
@ -32,6 +33,23 @@ class TXT(Record):
|
||||
return self.txt_data
|
||||
|
||||
def _from_string(self, value):
|
||||
if (not value.startswith('"') and not value.endswith('"')):
|
||||
# value with spaces should be quoted as per RFC1035 5.1
|
||||
for element in value:
|
||||
if element.isspace():
|
||||
err = ("Empty spaces are not allowed in TXT record, "
|
||||
"unless wrapped in double quotes.")
|
||||
raise InvalidObject(err)
|
||||
else:
|
||||
# quotes within value should be escaped with backslash
|
||||
strip_value = value.strip('"')
|
||||
for index, char in enumerate(strip_value):
|
||||
if char == '"':
|
||||
if strip_value[index - 1] != "\\":
|
||||
err = ("Quotation marks should be escaped with "
|
||||
"backslash.")
|
||||
raise InvalidObject(err)
|
||||
|
||||
self.txt_data = value
|
||||
|
||||
# The record type is defined in the RFC. This will be used when the record
|
||||
|
33
designate/tests/unit/test_objects/test_rrdata_spf.py
Normal file
33
designate/tests/unit/test_objects/test_rrdata_spf.py
Normal file
@ -0,0 +1,33 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from oslo_log import log as logging
|
||||
import oslotest.base
|
||||
import testtools
|
||||
|
||||
from designate import exceptions
|
||||
|
||||
from designate import objects
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RRDataSPFTest(oslotest.base.BaseTestCase):
|
||||
|
||||
def test_reject_non_quoted_spaces(self):
|
||||
record = objects.SPF(data='foo bar')
|
||||
with testtools.ExpectedException(exceptions.InvalidObject):
|
||||
record.validate()
|
||||
|
||||
def test_reject_non_escaped_quotes(self):
|
||||
record = objects.SPF(data='foo"bar')
|
||||
with testtools.ExpectedException(exceptions.InvalidObject):
|
||||
record.validate()
|
33
designate/tests/unit/test_objects/test_rrdata_txt.py
Normal file
33
designate/tests/unit/test_objects/test_rrdata_txt.py
Normal file
@ -0,0 +1,33 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from oslo_log import log as logging
|
||||
import oslotest.base
|
||||
import testtools
|
||||
|
||||
from designate import exceptions
|
||||
|
||||
from designate import objects
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RRDataTXTTest(oslotest.base.BaseTestCase):
|
||||
|
||||
def test_reject_non_quoted_spaces(self):
|
||||
record = objects.TXT(data='foo bar')
|
||||
with testtools.ExpectedException(exceptions.InvalidObject):
|
||||
record.validate()
|
||||
|
||||
def test_reject_non_escaped_quotes(self):
|
||||
record = objects.TXT(data='foo"bar')
|
||||
with testtools.ExpectedException(exceptions.InvalidObject):
|
||||
record.validate()
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
TXT and SPF records are now validated for empty spaces in the values.
|
||||
If record value has empty space it should use "" quotation according to
|
||||
RFC-1035 section 5.1. Use of single quotation mark within record value
|
||||
requires quote symbol to be escaped with backslash. Bug-1755788
|
Loading…
Reference in New Issue
Block a user