mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #2115 from jmchilton/dev-merge
Merge release into latest dev.
This commit is contained in:
@@ -442,7 +442,7 @@ class AdminToolshed( AdminGalaxy ):
|
||||
# Avoid caching
|
||||
trans.response.headers['Pragma'] = 'no-cache'
|
||||
trans.response.headers['Expires'] = '0'
|
||||
return suc.get_repository_file_contents( trans.app, file_path, repository_id )
|
||||
return suc.get_repository_file_contents( trans.app, file_path, repository_id, is_admin=True )
|
||||
|
||||
@web.expose
|
||||
@web.require_admin
|
||||
@@ -973,7 +973,7 @@ class AdminToolshed( AdminGalaxy ):
|
||||
# Avoid caching
|
||||
trans.response.headers['Pragma'] = 'no-cache'
|
||||
trans.response.headers['Expires'] = '0'
|
||||
return suc.open_repository_files_folder( trans.app, folder_path, repository_id )
|
||||
return suc.open_repository_files_folder( trans.app, folder_path, repository_id, is_admin=True )
|
||||
|
||||
@web.expose
|
||||
@web.require_admin
|
||||
|
||||
@@ -1471,7 +1471,8 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
# Avoid caching
|
||||
trans.response.headers['Pragma'] = 'no-cache'
|
||||
trans.response.headers['Expires'] = '0'
|
||||
return suc.get_repository_file_contents( trans.app, file_path, repository_id )
|
||||
is_admin = trans.user_is_admin()
|
||||
return suc.get_repository_file_contents( trans.app, file_path, repository_id, is_admin )
|
||||
|
||||
@web.expose
|
||||
def get_functional_test_rss( self, trans, **kwd ):
|
||||
@@ -2424,7 +2425,8 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
# Avoid caching
|
||||
trans.response.headers['Pragma'] = 'no-cache'
|
||||
trans.response.headers['Expires'] = '0'
|
||||
return suc.open_repository_files_folder( trans.app, folder_path, repository_id )
|
||||
is_admin = trans.user_is_admin()
|
||||
return suc.open_repository_files_folder( trans.app, folder_path, repository_id, is_admin )
|
||||
|
||||
@web.expose
|
||||
def preview_tools_in_changeset( self, trans, repository_id, **kwd ):
|
||||
|
||||
@@ -636,13 +636,13 @@ def get_repository_for_dependency_relationship( app, tool_shed, name, owner, cha
|
||||
return repository
|
||||
|
||||
|
||||
def get_repository_file_contents( app, file_path, repository_id ):
|
||||
def get_repository_file_contents( app, file_path, repository_id, is_admin=False ):
|
||||
"""Return the display-safe contents of a repository file for display in a browser."""
|
||||
safe_str = ''
|
||||
if not is_path_within_repo( app, file_path, repository_id ):
|
||||
if not is_path_browsable( app, file_path, repository_id, is_admin ):
|
||||
log.warning( 'Request tries to access a file outside of the repository location. File path: %s', file_path )
|
||||
return 'Invalid file path'
|
||||
# Symlink targets are checked by is_path_within_repo
|
||||
# Symlink targets are checked by is_path_browsable
|
||||
if os.path.islink( file_path ):
|
||||
safe_str = 'link to: ' + basic_util.to_html_string( os.readlink( file_path ) )
|
||||
return safe_str
|
||||
@@ -1150,14 +1150,13 @@ def is_tool_shed_client( app ):
|
||||
return hasattr( app, "install_model" )
|
||||
|
||||
|
||||
def open_repository_files_folder( app, folder_path, repository_id ):
|
||||
def open_repository_files_folder( app, folder_path, repository_id, is_admin=False ):
|
||||
"""
|
||||
Return a list of dictionaries, each of which contains information for a file or directory contained
|
||||
within a directory in a repository file hierarchy.
|
||||
"""
|
||||
# Symlink targets are checked by is_path_within_repo
|
||||
if not is_path_within_repo( app, folder_path, repository_id ):
|
||||
log.warning( 'Request tries to access a folder outside of the repository location. Folder path: %s', folder_path )
|
||||
if not is_path_browsable( app, folder_path, repository_id, is_admin ):
|
||||
log.warning( 'Request tries to access a folder outside of the allowed locations. Folder path: %s', folder_path )
|
||||
return []
|
||||
try:
|
||||
files_list = get_repository_files( folder_path )
|
||||
@@ -1170,11 +1169,11 @@ def open_repository_files_folder( app, folder_path, repository_id ):
|
||||
is_folder = False
|
||||
full_path = os.path.join( folder_path, filename )
|
||||
is_link = os.path.islink( full_path )
|
||||
path_is_within_repo = is_path_within_repo( app, full_path, repository_id )
|
||||
if is_link and not path_is_within_repo:
|
||||
path_is_browsable = is_path_browsable( app, full_path, repository_id )
|
||||
if is_link and not path_is_browsable:
|
||||
log.warning( 'Valid folder contains a symlink outside of the repository location. Link found in: ' + str( full_path ) )
|
||||
if filename:
|
||||
if os.path.isdir( full_path ) and path_is_within_repo:
|
||||
if os.path.isdir( full_path ) and path_is_browsable:
|
||||
# Append a '/' character so that our jquery dynatree will function properly.
|
||||
filename = '%s/' % filename
|
||||
full_path = '%s/' % full_path
|
||||
@@ -1188,9 +1187,20 @@ def open_repository_files_folder( app, folder_path, repository_id ):
|
||||
return folder_contents
|
||||
|
||||
|
||||
def is_path_browsable( app, path, repository_id, is_admin=False ):
|
||||
"""
|
||||
Detects whether the given path is browsable i.e. is within the
|
||||
allowed repository folders. Admins can additionaly browse folders
|
||||
with tool dependencies.
|
||||
"""
|
||||
if is_admin and is_path_within_dependency_dir( app, path ):
|
||||
return True
|
||||
return is_path_within_repo( app, path, repository_id)
|
||||
|
||||
|
||||
def is_path_within_repo( app, path, repository_id ):
|
||||
"""
|
||||
Detect whether the given path is within the repository folde ron the disk.
|
||||
Detect whether the given path is within the repository folder on the disk.
|
||||
Use to filter malicious symlinks targeting outside paths.
|
||||
"""
|
||||
repo_path = os.path.abspath( get_repository_by_id( app, repository_id ).repo_path( app ) )
|
||||
@@ -1198,6 +1208,20 @@ def is_path_within_repo( app, path, repository_id ):
|
||||
return os.path.commonprefix( [ repo_path, resolved_path ] ) == repo_path
|
||||
|
||||
|
||||
def is_path_within_dependency_dir( app, path ):
|
||||
"""
|
||||
Detect whether the given path is within the tool_dependency_dir folder on the disk.
|
||||
(Specified by the config option). Use to filter malicious symlinks targeting outside paths.
|
||||
"""
|
||||
allowed = False
|
||||
resolved_path = os.path.realpath( path )
|
||||
tool_dependency_dir = app.config.get( 'tool_dependency_dir', None )
|
||||
if tool_dependency_dir:
|
||||
dependency_path = os.path.abspath( tool_dependency_dir )
|
||||
allowed = os.path.commonprefix( [ dependency_path, resolved_path ] ) == dependency_path
|
||||
return allowed
|
||||
|
||||
|
||||
def repository_was_previously_installed( app, tool_shed_url, repository_name, repo_info_tuple, from_tip=False ):
|
||||
"""
|
||||
Find out if a repository is already installed into Galaxy - there are several scenarios where this
|
||||
|
||||
Reference in New Issue
Block a user