Skip to content

Commit fccce96

Browse files
Merge pull request #276 from vladimir-v-diaz/supported-uri-schemes
Add Configuration Option for Supported URI Schemes
2 parents fb7dfaa + 16685d2 commit fccce96

File tree

3 files changed

+59
-4
lines changed

3 files changed

+59
-4
lines changed

tests/test_download.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,12 @@ def test_download_url_to_tempfileobj_and_performance(self):
160160
def test_download_url_to_tempfileobj_and_urls(self):
161161

162162
download_file = download.safe_download
163+
unsafe_download_file = download.unsafe_download
163164

164165
self.assertRaises(tuf.FormatError,
165166
download_file, None, self.target_data_length)
166167

167-
self.assertRaises(ValueError,
168+
self.assertRaises(tuf.FormatError,
168169
download_file,
169170
self.random_string(), self.target_data_length)
170171

@@ -177,8 +178,15 @@ def test_download_url_to_tempfileobj_and_urls(self):
177178
download_file,
178179
'http://localhost:' + str(self.PORT+1) + '/' + self.random_string(),
179180
self.target_data_length)
180-
181181

182+
# Specify an unsupported URI scheme.
183+
url_with_unsupported_uri = self.url.replace('http', 'file')
184+
self.assertRaises(tuf.FormatError, download_file, url_with_unsupported_uri,
185+
self.target_data_length)
186+
self.assertRaises(tuf.FormatError, unsafe_download_file,
187+
url_with_unsupported_uri, self.target_data_length)
188+
189+
182190

183191
def test__get_opener(self):
184192
# Test normal case.

tuf/conf.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,10 @@
101101
# to generate the digests listed in metadata and prepended to the filenames of
102102
# consistent snapshots.
103103
REPOSITORY_HASH_ALGORITHMS = ['sha256']
104+
105+
# Software updaters that integrate the framework are required to specify
106+
# the URL prefix for the mirrors that clients can contact to download updates.
107+
# The following URI schemes are those that download.py support. By default,
108+
# the ['http', 'https'] URI schemes are supported, but may be modified by
109+
# integrators to schemes that they wish to support for their integration.
110+
SUPPORTED_URI_SCHEMES = ['http', 'https']

tuf/download.py

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ def safe_download(url, required_length):
7070
7171
<Arguments>
7272
url:
73-
A URL string that represents the location of the file.
73+
A URL string that represents the location of the file. The URI scheme
74+
component must be one of 'tuf.conf.SUPPORTED_URI_SCHEMES'.
7475
7576
required_length:
7677
An integer value representing the length of the file. This is an exact
@@ -92,6 +93,25 @@ def safe_download(url, required_length):
9293
A 'tuf.util.TempFile' file-like object that points to the contents of 'url'.
9394
"""
9495

96+
# Do all of the arguments have the appropriate format?
97+
# Raise 'tuf.FormatError' if there is a mismatch.
98+
tuf.formats.URL_SCHEMA.check_match(url)
99+
tuf.formats.LENGTH_SCHEMA.check_match(required_length)
100+
101+
# Ensure 'url' specifies one of the URI schemes in
102+
# 'tuf.conf.SUPPORTED_URI_SCHEMES'. Be default, ['http', 'https'] is
103+
# supported. If the URI scheme of 'url' is empty or "file", files on the
104+
# local system can be accessed. Unexpected files may be accessed by
105+
# compromised metadata (unlikely to happen if targets.json metadata is signed
106+
# with offline keys).
107+
parsed_url = six.moves.urllib.parse.urlparse(url)
108+
109+
if parsed_url.scheme not in tuf.conf.SUPPORTED_URI_SCHEMES:
110+
message = \
111+
repr(url) + ' specifies an unsupported URI scheme. Supported ' + \
112+
' URI Schemes: ' + repr(tuf.conf.SUPPORTED_URI_SCHEMES)
113+
raise tuf.FormatError(message)
114+
95115
return _download_file(url, required_length, STRICT_REQUIRED_LENGTH=True)
96116

97117

@@ -114,7 +134,8 @@ def unsafe_download(url, required_length):
114134
115135
<Arguments>
116136
url:
117-
A URL string that represents the location of the file.
137+
A URL string that represents the location of the file. The URI scheme
138+
component must be one of 'tuf.conf.SUPPORTED_URI_SCHEMES'.
118139
119140
required_length:
120141
An integer value representing the length of the file. This is an upper
@@ -136,6 +157,25 @@ def unsafe_download(url, required_length):
136157
A 'tuf.util.TempFile' file-like object that points to the contents of 'url'.
137158
"""
138159

160+
# Do all of the arguments have the appropriate format?
161+
# Raise 'tuf.FormatError' if there is a mismatch.
162+
tuf.formats.URL_SCHEMA.check_match(url)
163+
tuf.formats.LENGTH_SCHEMA.check_match(required_length)
164+
165+
# Ensure 'url' specifies one of the URI schemes in
166+
# 'tuf.conf.SUPPORTED_URI_SCHEMES'. Be default, ['http', 'https'] is
167+
# supported. If the URI scheme of 'url' is empty or "file", files on the
168+
# local system can be accessed. Unexpected files may be accessed by
169+
# compromised metadata (unlikely to happen if targets.json metadata is signed
170+
# with offline keys).
171+
parsed_url = six.moves.urllib.parse.urlparse(url)
172+
173+
if parsed_url.scheme not in tuf.conf.SUPPORTED_URI_SCHEMES:
174+
message = \
175+
repr(url) + ' specifies an unsupported URI scheme. Supported ' + \
176+
' URI Schemes: ' + repr(tuf.conf.SUPPORTED_URI_SCHEMES)
177+
raise tuf.FormatError(message)
178+
139179
return _download_file(url, required_length, STRICT_REQUIRED_LENGTH=False)
140180

141181

0 commit comments

Comments
 (0)