Skip to content

Commit 9eef0bd

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 66efa51 commit 9eef0bd

File tree

1 file changed

+53
-83
lines changed

1 file changed

+53
-83
lines changed

tuf/repository_tool.py

Lines changed: 53 additions & 83 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)
@@ -2241,9 +2240,7 @@ def delegate(self, rolename, public_keys, paths, threshold=1,
22412240
22422241
securesystemslib.exceptions.Error, if the delegated role already exists.
22432242
2244-
tuf.exceptions.InvalidNameError, if any path in 'paths' or any
2245-
target in 'list_of_targets' is not relative (starts with a directory
2246-
separator).
2243+
tuf.exceptions.InvalidNameError, if 'pathname' does not match pattern.
22472244
22482245
<Side Effects>
22492246
A new Target object is created for 'rolename' that is accessible to the
@@ -2292,24 +2289,19 @@ def delegate(self, rolename, public_keys, paths, threshold=1,
22922289

22932290
if list_of_targets:
22942291
for target in list_of_targets:
2295-
# Check if the target path is relative and normalize it. File's
2292+
# Check if the target path is relative or raise an exception. File's
22962293
# existence on the file system is not verified. If the file does not
22972294
# exist relative to the targets directory, later calls to write()
22982295
# will fail.
2299-
rel_targetpath = self._check_relpath(target)
2300-
relative_targetpaths.update({rel_targetpath: {}})
2301-
2302-
# A list of relative and verified paths or glob patterns to be added to the
2303-
# child role's entry in the parent's delegations field.
2304-
relative_paths = []
2296+
self._check_path(target)
2297+
relative_targetpaths.update({target: {}})
23052298

23062299
for path in paths:
2307-
# Check if the delegated paths or glob patterns are relative and
2308-
# normalize them. Paths' existense on the file system is not verified.
2309-
# If the path is incorrect, the targetfile won't be matched successfully
2310-
# during a client update.
2311-
path = self._check_relpath(path)
2312-
relative_paths.append(path)
2300+
# Check if the delegated paths or glob patterns are relative or
2301+
# raise an exception. Paths' existence on the file system is not
2302+
# verified. If the path is incorrect, the targetfile won't be matched
2303+
# successfully during a client update.
2304+
self._check_path(path)
23132305

23142306
# Create a new Targets object for the 'rolename' delegation. An initial
23152307
# expiration is set (3 months from the current time).
@@ -2340,8 +2332,8 @@ def delegate(self, rolename, public_keys, paths, threshold=1,
23402332
'terminating': terminating,
23412333
'paths': list(roleinfo['paths'].keys())}
23422334

2343-
if relative_paths:
2344-
roleinfo['paths'] = relative_paths
2335+
if paths:
2336+
roleinfo['paths'] = paths
23452337

23462338
if path_hash_prefixes:
23472339
roleinfo['path_hash_prefixes'] = path_hash_prefixes
@@ -2485,8 +2477,7 @@ def delegate_hashed_bins(self, list_of_targets, keys_of_hashed_bins,
24852477
2, or one of the targets in 'list_of_targets' is not relative to the
24862478
repository's targets directory.
24872479
2488-
tuf.exceptions.InvalidNameError, if any target in 'list_of_targets'
2489-
is not relative (starts with a directory separator).
2480+
tuf.exceptions.InvalidNameError, if 'pathname' does not match pattern.
24902481
24912482
<Side Effects>
24922483
Delegates multiple target roles from the current parent role.
@@ -2535,7 +2526,7 @@ def delegate_hashed_bins(self, list_of_targets, keys_of_hashed_bins,
25352526
# Check if the target path is relative and normalize it. File's existence
25362527
# on the file system is not verified. If the file does not exist relative
25372528
# to the targets directory, later calls to write() will fail.
2538-
target_path = self._check_relpath(target_path)
2529+
self._check_path(target_path)
25392530

25402531
# Determine the hash prefix of 'target_path' by computing the digest of
25412532
# its path relative to the targets directory.
@@ -2706,7 +2697,7 @@ def delegations(self):
27062697

27072698

27082699

2709-
def _check_relpath(self, pathname):
2700+
def _check_path(self, pathname):
27102701
"""
27112702
<Purpose>
27122703
Check if a path matches the definition of a PATHPATTERN or a
@@ -2722,44 +2713,23 @@ def _check_relpath(self, pathname):
27222713
securesystemslib.exceptions.FormatError, if 'pathname' is improperly
27232714
formatted.
27242715
2725-
tuf.exceptions.InvalidNameError, if 'pathname' starts with a directory
2726-
separator.
2727-
2728-
<Side Effects>
2729-
Normalizes pathname.
2716+
tuf.exceptions.InvalidNameError, if 'pathname' does not match pattern.
27302717
27312718
<Returns>
2732-
The normazlied 'pathname'.
2719+
None.
27332720
"""
27342721

27352722
tuf.formats.RELPATH_SCHEMA.check_match(pathname)
27362723

2737-
if os.path.isabs(pathname):
2738-
raise tuf.exceptions.InvalidNameError(repr(pathname) + ' contains a leading'
2739-
' path separator. All paths should be relative to the repository\'s'
2740-
' targets directory.')
2741-
2742-
# Trigger a warning when the path contains '..' since directories
2743-
# upper than the current cannot be resolved by normpath.
2744-
dir_list = pathname.split(os.sep)
2745-
for dirname in dir_list:
2746-
if dirname == '..':
2747-
logger.warning('Path ' + repr(pathname) + ' contains \'..\'.'
2748-
' Parent directory may not be resolved.')
2749-
break
2750-
2751-
pathname = os.path.normpath(pathname)
2752-
2753-
# Trigger a warning in case path name is not passed as a relative
2754-
# to the targets directory but starts with it instead. Ensure a trailing
2755-
# path separator with os.path.join(path, '').
2756-
targets_directory = os.path.join(self._targets_directory, '')
2757-
if pathname.startswith(targets_directory):
2758-
logger.warning(repr(pathname) + ' should not include the'
2759-
' repository\'s targets'
2760-
' directory: ' + repr(self._targets_directory))
2761-
2762-
return pathname
2724+
if '\\' in pathname:
2725+
raise tuf.exceptions.InvalidNameError('Path ' + repr(pathname)
2726+
+ ' does not use the forward slash (/) as directory separator.')
2727+
2728+
if pathname.startswith(os.sep):
2729+
raise tuf.exceptions.InvalidNameError('Path ' + repr(pathname)
2730+
+ ' starts with a directory separator. All paths should be relative'
2731+
' to targets directory.')
2732+
27632733

27642734

27652735

0 commit comments

Comments
 (0)