Skip to content

Commit ba8ffd2

Browse files
committed
Rework _check_relpath() method
Adopt a stict behavor allowing only paths that match the definition of a PATHPATTERN or aTARGETPATH (use the forward slash (/) as directory separator and do not start with a directory separator). Raise an exception otherwise. Rename the method to a more general _check_path(). Signed-off-by: Teodora Sechkova <[email protected]>
1 parent ba91a93 commit ba8ffd2

File tree

1 file changed

+57
-86
lines changed

1 file changed

+57
-86
lines changed

tuf/repository_tool.py

Lines changed: 57 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1854,8 +1854,7 @@ def add_paths(self, paths, child_rolename):
18541854
securesystemslib.exceptions.Error, if 'child_rolename' has not been
18551855
delegated yet.
18561856
1857-
tuf.exceptions.InvalidNameError, if any path in 'paths' starts with
1858-
a directory separator.
1857+
tuf.exceptions.InvalidNameError, if 'pathname' does not match pattern.
18591858
18601859
<Side Effects>
18611860
Modifies this Targets' delegations field.
@@ -1882,11 +1881,11 @@ def add_paths(self, paths, child_rolename):
18821881
' not exist.')
18831882

18841883
for path in paths:
1885-
# Check if the delegated paths or glob patterns are relative and
1886-
# normalize them. Paths' existence on the file system is not verified.
1887-
# If the path is incorrect, the targetfile won't be matched successfully
1888-
# during a client update.
1889-
path = self._check_relpath(path)
1884+
# Check if the delegated paths or glob patterns are relative and use
1885+
# forward slash as a separator or raise an exception. Paths' existence
1886+
# on the file system is not verified. If the path is incorrect,
1887+
# the targetfile won't be matched successfully during a client update.
1888+
self._check_path(path)
18901889
relative_paths.append(path)
18911890

18921891
# Get the current role's roleinfo, so that its delegations field can be
@@ -1945,8 +1944,7 @@ def add_target(self, filepath, custom=None, fileinfo=None):
19451944
securesystemslib.exceptions.FormatError, if 'filepath' is improperly
19461945
formatted.
19471946
1948-
tuf.exceptions.InvalidNameError, if 'filepath' is not relative (starts
1949-
with a directory separator).
1947+
tuf.exceptions.InvalidNameError, if 'pathname' does not match pattern.
19501948
19511949
<Side Effects>
19521950
Adds 'filepath' to this role's list of targets. This role's
@@ -1977,28 +1975,29 @@ def add_target(self, filepath, custom=None, fileinfo=None):
19771975
# Add 'filepath' (i.e., relative to the targets directory) to the role's
19781976
# list of targets. 'filepath' will not be verified as an allowed path
19791977
# according to some delegating role. Not verifying 'filepath' here allows
1980-
# freedom to add targets and parent restrictions in any order, minimize the
1981-
# number of times these checks are performed, and allow any role to
1978+
# freedom to add targets and parent restrictions in any order, minimize
1979+
# the number of times these checks are performed, and allow any role to
19821980
# delegate trust of packages to this Targets role.
19831981

1984-
# Check if the target path is relative and normalize it. File's existence
1985-
# on the file system is not verified. If the file does not exist relative
1986-
# to the targets directory, later calls to write() will fail.
1987-
relative_path = self._check_relpath(filepath)
1982+
# Check if the target is relative and uses forward slash as a separator
1983+
# or raise an exception. File's existence on the file system is not
1984+
# verified. If the file does not exist relative to the targets directory,
1985+
# later calls to write() will fail.
1986+
self._check_path(filepath)
19881987

19891988
# Update the role's 'tuf.roledb.py' entry and avoid duplicates.
19901989
roleinfo = tuf.roledb.get_roleinfo(self._rolename, self._repository_name)
19911990

1992-
if relative_path not in roleinfo['paths']:
1993-
logger.debug('Adding new target: ' + repr(relative_path))
1991+
if filepath not in roleinfo['paths']:
1992+
logger.debug('Adding new target: ' + repr(filepath))
19941993

19951994
else:
1996-
logger.debug('Replacing target: ' + repr(relative_path))
1995+
logger.debug('Replacing target: ' + repr(filepath))
19971996

19981997
if fileinfo:
1999-
roleinfo['paths'].update({relative_path: fileinfo})
1998+
roleinfo['paths'].update({filepath: fileinfo})
20001999
else:
2001-
roleinfo['paths'].update({relative_path: {'custom': custom}})
2000+
roleinfo['paths'].update({filepath: {'custom': custom}})
20022001

20032002
tuf.roledb.update_roleinfo(self._rolename, roleinfo,
20042003
repository_name=self._repository_name)
@@ -2025,8 +2024,7 @@ def add_targets(self, list_of_targets):
20252024
securesystemslib.exceptions.FormatError, if the arguments are improperly
20262025
formatted.
20272026
2028-
tuf.exceptions.InvalidNameError, if any target in 'list_of_targets'
2029-
is not relative (starts with a directory separator).
2027+
tuf.exceptions.InvalidNameError, if 'pathname' does not match pattern.
20302028
20312029
<Side Effects>
20322030
This Targets' roleinfo is updated with the paths in 'list_of_targets'.
@@ -2044,14 +2042,15 @@ def add_targets(self, list_of_targets):
20442042
# Update the tuf.roledb entry.
20452043
relative_list_of_targets = []
20462044

2047-
# Ensure the paths in 'list_of_targets' are valid and are located in the
2048-
# repository's targets directory. The paths of 'list_of_targets' will be
2049-
# verified as allowed paths according to this Targets parent role when
2050-
# write() or writeall() is called. Not verifying filepaths here allows the
2051-
# freedom to add targets and parent restrictions in any order, and minimize
2052-
# the number of times these checks are performed.
2045+
# Ensure the paths in 'list_of_targets' are relative and use forward slash
2046+
# as a separator or raise an exception. The paths of 'list_of_targets'
2047+
# will be verified as existing and allowed paths according to this Targets
2048+
# parent role when write() or writeall() is called. Not verifying
2049+
# filepaths here allows the freedom to add targets and parent restrictions
2050+
# in any order and minimize the number of times these checks are performed.
20532051
for target in list_of_targets:
2054-
relative_list_of_targets.append(self._check_relpath(target))
2052+
self._check_path(target)
2053+
relative_list_of_targets.append(target)
20552054

20562055
# Update this Targets 'tuf.roledb.py' entry.
20572056
roleinfo = tuf.roledb.get_roleinfo(self._rolename, self._repository_name)
@@ -2286,9 +2285,7 @@ def delegate(self, rolename, public_keys, paths, threshold=1,
22862285
22872286
securesystemslib.exceptions.Error, if the delegated role already exists.
22882287
2289-
tuf.exceptions.InvalidNameError, if any path in 'paths' or any
2290-
target in 'list_of_targets' is not relative (starts with a directory
2291-
separator).
2288+
tuf.exceptions.InvalidNameError, if 'pathname' does not match pattern.
22922289
22932290
<Side Effects>
22942291
A new Target object is created for 'rolename' that is accessible to the
@@ -2325,24 +2322,19 @@ def delegate(self, rolename, public_keys, paths, threshold=1,
23252322

23262323
if list_of_targets:
23272324
for target in list_of_targets:
2328-
# Check if the target path is relative and normalize it. File's
2325+
# Check if the target path is relative or raise an exception. File's
23292326
# existence on the file system is not verified. If the file does not
23302327
# exist relative to the targets directory, later calls to write()
23312328
# will fail.
2332-
rel_targetpath = self._check_relpath(target)
2333-
relative_targetpaths.update({rel_targetpath: {}})
2334-
2335-
# A list of relative and verified paths or glob patterns to be added to the
2336-
# child role's entry in the parent's delegations field.
2337-
relative_paths = []
2329+
self._check_path(target)
2330+
relative_targetpaths.update({target: {}})
23382331

23392332
for path in paths:
2340-
# Check if the delegated paths or glob patterns are relative and
2341-
# normalize them. Paths' existense on the file system is not verified.
2342-
# If the path is incorrect, the targetfile won't be matched successfully
2343-
# during a client update.
2344-
path = self._check_relpath(path)
2345-
relative_paths.append(path)
2333+
# Check if the delegated paths or glob patterns are relative or
2334+
# raise an exception. Paths' existence on the file system is not
2335+
# verified. If the path is incorrect, the targetfile won't be matched
2336+
# successfully during a client update.
2337+
self._check_path(path)
23462338

23472339
# The new targets object is added as an attribute to this Targets object.
23482340
new_targets_object = self._create_delegated_target(rolename, keyids,
@@ -2356,8 +2348,8 @@ def delegate(self, rolename, public_keys, paths, threshold=1,
23562348
'terminating': terminating,
23572349
'paths': list(relative_targetpaths.keys())}
23582350

2359-
if relative_paths:
2360-
roleinfo['paths'] = relative_paths
2351+
if paths:
2352+
roleinfo['paths'] = paths
23612353

23622354
if path_hash_prefixes:
23632355
roleinfo['path_hash_prefixes'] = path_hash_prefixes
@@ -2498,8 +2490,7 @@ def delegate_hashed_bins(self, list_of_targets, keys_of_hashed_bins,
24982490
2, or one of the targets in 'list_of_targets' is not relative to the
24992491
repository's targets directory.
25002492
2501-
tuf.exceptions.InvalidNameError, if any target in 'list_of_targets'
2502-
is not relative (starts with a directory separator).
2493+
tuf.exceptions.InvalidNameError, if 'pathname' does not match pattern.
25032494
25042495
<Side Effects>
25052496
Delegates multiple target roles from the current parent role.
@@ -2545,10 +2536,11 @@ def delegate_hashed_bins(self, list_of_targets, keys_of_hashed_bins,
25452536
ordered_roles.append(role)
25462537

25472538
for target_path in list_of_targets:
2548-
# Check if the target path is relative and normalize it. File's existence
2549-
# on the file system is not verified. If the file does not exist relative
2550-
# to the targets directory, later calls to write() will fail.
2551-
target_path = self._check_relpath(target_path)
2539+
# Check if the target path is relative or raise an exception. File's
2540+
# existence on the file system is not verified. If the file does not
2541+
# exist relative to the targets directory, later calls to write() and
2542+
# writeall() will fail.
2543+
self._check_path(target_path)
25522544

25532545
# Determine the hash prefix of 'target_path' by computing the digest of
25542546
# its path relative to the targets directory.
@@ -2764,7 +2756,7 @@ def delegations(self):
27642756

27652757

27662758

2767-
def _check_relpath(self, pathname):
2759+
def _check_path(self, pathname):
27682760
"""
27692761
<Purpose>
27702762
Check if a path matches the definition of a PATHPATTERN or a
@@ -2780,44 +2772,23 @@ def _check_relpath(self, pathname):
27802772
securesystemslib.exceptions.FormatError, if 'pathname' is improperly
27812773
formatted.
27822774
2783-
tuf.exceptions.InvalidNameError, if 'pathname' starts with a directory
2784-
separator.
2785-
2786-
<Side Effects>
2787-
Normalizes pathname.
2775+
tuf.exceptions.InvalidNameError, if 'pathname' does not match pattern.
27882776
27892777
<Returns>
2790-
The normazlied 'pathname'.
2778+
None.
27912779
"""
27922780

27932781
tuf.formats.RELPATH_SCHEMA.check_match(pathname)
27942782

2795-
if os.path.isabs(pathname):
2796-
raise tuf.exceptions.InvalidNameError(repr(pathname) + ' contains a leading'
2797-
' path separator. All paths should be relative to the repository\'s'
2798-
' targets directory.')
2799-
2800-
# Trigger a warning when the path contains '..' since directories
2801-
# upper than the current cannot be resolved by normpath.
2802-
dir_list = pathname.split(os.sep)
2803-
for dirname in dir_list:
2804-
if dirname == '..':
2805-
logger.warning('Path ' + repr(pathname) + ' contains \'..\'.'
2806-
' Parent directory may not be resolved.')
2807-
break
2808-
2809-
pathname = os.path.normpath(pathname)
2810-
2811-
# Trigger a warning in case path name is not passed as a relative
2812-
# to the targets directory but starts with it instead. Ensure a trailing
2813-
# path separator with os.path.join(path, '').
2814-
targets_directory = os.path.join(self._targets_directory, '')
2815-
if pathname.startswith(targets_directory):
2816-
logger.warning(repr(pathname) + ' should not include the'
2817-
' repository\'s targets'
2818-
' directory: ' + repr(self._targets_directory))
2819-
2820-
return pathname
2783+
if '\\' in pathname:
2784+
raise tuf.exceptions.InvalidNameError('Path ' + repr(pathname)
2785+
+ ' does not use the forward slash (/) as directory separator.')
2786+
2787+
if pathname.startswith(os.sep):
2788+
raise tuf.exceptions.InvalidNameError('Path ' + repr(pathname)
2789+
+ ' starts with a directory separator. All paths should be relative'
2790+
' to targets directory.')
2791+
28212792

28222793

28232794

0 commit comments

Comments
 (0)