mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-09 23:15:58 -06:00
Ensure that the authenticated users can't access each other's directories and files by providing relative paths. #5734
This commit is contained in:
parent
83b207e7da
commit
8b236e7bc8
@ -19,8 +19,9 @@ from flask_babel import gettext as _
|
||||
from flask_security import login_required, current_user
|
||||
from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc
|
||||
from pgadmin.utils import PgAdminModule, get_storage_directory, html, \
|
||||
fs_short_path, document_dir, does_utility_exist, get_server
|
||||
from pgadmin.utils.ajax import make_json_response, bad_request
|
||||
fs_short_path, document_dir, does_utility_exist, get_server, \
|
||||
filename_with_file_manager_path
|
||||
from pgadmin.utils.ajax import make_json_response, bad_request, unauthorized
|
||||
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
from pgadmin.model import Server, SharedServer
|
||||
@ -189,40 +190,6 @@ def script():
|
||||
)
|
||||
|
||||
|
||||
def filename_with_file_manager_path(_file, create_file=True):
|
||||
"""
|
||||
Args:
|
||||
file: File name returned from client file manager
|
||||
create_file: Set flag to False when file creation doesn't required
|
||||
Returns:
|
||||
Filename to use for backup with full path taken from preference
|
||||
"""
|
||||
# Set file manager directory from preference
|
||||
storage_dir = get_storage_directory()
|
||||
if storage_dir:
|
||||
_file = os.path.join(storage_dir, _file.lstrip('/').lstrip('\\'))
|
||||
elif not os.path.isabs(_file):
|
||||
_file = os.path.join(document_dir(), _file)
|
||||
|
||||
def short_filepath():
|
||||
short_path = fs_short_path(_file)
|
||||
# fs_short_path() function may return empty path on Windows
|
||||
# if directory doesn't exists. In that case we strip the last path
|
||||
# component and get the short path.
|
||||
if os.name == 'nt' and short_path == '':
|
||||
base_name = os.path.basename(_file)
|
||||
dir_name = os.path.dirname(_file)
|
||||
short_path = fs_short_path(dir_name) + '\\' + base_name
|
||||
return short_path
|
||||
|
||||
if create_file:
|
||||
# Touch the file to get the short path of the file on windows.
|
||||
with open(_file, 'a'):
|
||||
return short_filepath()
|
||||
|
||||
return short_filepath()
|
||||
|
||||
|
||||
def _get_args_params_values(data, conn, backup_obj_type, backup_file, server,
|
||||
manager):
|
||||
"""
|
||||
@ -367,6 +334,8 @@ def create_backup_objects_job(sid):
|
||||
try:
|
||||
backup_file = filename_with_file_manager_path(
|
||||
data['file'], (data.get('format', '') != 'directory'))
|
||||
except PermissionError as e:
|
||||
return unauthorized(errormsg=str(e))
|
||||
except Exception as e:
|
||||
return bad_request(errormsg=str(e))
|
||||
|
||||
|
@ -17,8 +17,9 @@ from flask_babel import gettext as _
|
||||
from flask_security import login_required, current_user
|
||||
from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc
|
||||
from pgadmin.utils import PgAdminModule, get_storage_directory, html, \
|
||||
fs_short_path, document_dir, IS_WIN, does_utility_exist
|
||||
from pgadmin.utils.ajax import make_json_response, bad_request
|
||||
fs_short_path, document_dir, IS_WIN, does_utility_exist, \
|
||||
filename_with_file_manager_path
|
||||
from pgadmin.utils.ajax import make_json_response, bad_request, unauthorized
|
||||
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
from pgadmin.model import Server
|
||||
@ -145,33 +146,6 @@ def script():
|
||||
)
|
||||
|
||||
|
||||
def filename_with_file_manager_path(_file, _present=False):
|
||||
"""
|
||||
Args:
|
||||
file: File name returned from client file manager
|
||||
|
||||
Returns:
|
||||
Filename to use for backup with full path taken from preference
|
||||
"""
|
||||
# Set file manager directory from preference
|
||||
storage_dir = get_storage_directory()
|
||||
|
||||
if storage_dir:
|
||||
_file = os.path.join(storage_dir, _file.lstrip('/').lstrip('\\'))
|
||||
elif not os.path.isabs(_file):
|
||||
_file = os.path.join(document_dir(), _file)
|
||||
|
||||
if not _present:
|
||||
# Touch the file to get the short path of the file on windows.
|
||||
with open(_file, 'a'):
|
||||
return fs_short_path(_file)
|
||||
else:
|
||||
if not os.path.isfile(_file):
|
||||
return None
|
||||
|
||||
return fs_short_path(_file)
|
||||
|
||||
|
||||
def _get_ignored_column_list(data, driver, conn):
|
||||
"""
|
||||
Get list of ignored columns for import/export.
|
||||
@ -297,7 +271,9 @@ def create_import_export_job(sid):
|
||||
if 'filename' in data:
|
||||
try:
|
||||
_file = filename_with_file_manager_path(
|
||||
data['filename'], data['is_import'])
|
||||
data['filename'], not data['is_import'])
|
||||
except PermissionError as e:
|
||||
return unauthorized(errormsg=str(e))
|
||||
except Exception as e:
|
||||
return bad_request(errormsg=str(e))
|
||||
|
||||
|
@ -20,10 +20,11 @@ from flask_security import login_required, current_user
|
||||
from pgadmin.utils import PgAdminModule
|
||||
from pgadmin.utils.ajax import bad_request
|
||||
from pgadmin.utils.constants import MIMETYPE_APP_JS
|
||||
from pgadmin.utils.ajax import make_json_response, internal_server_error
|
||||
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
||||
unauthorized
|
||||
from pgadmin.model import ServerGroup, Server
|
||||
from pgadmin.utils import clear_database_servers, dump_database_servers,\
|
||||
load_database_servers, validate_json_data
|
||||
load_database_servers, validate_json_data, filename_with_file_manager_path
|
||||
from urllib.parse import unquote
|
||||
from pgadmin.utils.paths import get_storage_directory
|
||||
|
||||
@ -118,6 +119,14 @@ def load_servers():
|
||||
|
||||
# retrieve storage directory path
|
||||
storage_manager_path = get_storage_directory()
|
||||
|
||||
try:
|
||||
file_path = filename_with_file_manager_path(file_path)
|
||||
except PermissionError as e:
|
||||
return unauthorized(errormsg=str(e))
|
||||
except Exception as e:
|
||||
return bad_request(errormsg=str(e))
|
||||
|
||||
if storage_manager_path:
|
||||
# generate full path of file
|
||||
file_path = os.path.join(
|
||||
|
@ -18,8 +18,10 @@ from flask_babel import gettext as _
|
||||
from flask_security import login_required, current_user
|
||||
from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc
|
||||
from pgadmin.utils import PgAdminModule, get_storage_directory, html, \
|
||||
fs_short_path, document_dir, does_utility_exist, get_server
|
||||
from pgadmin.utils.ajax import make_json_response, bad_request
|
||||
fs_short_path, document_dir, does_utility_exist, get_server, \
|
||||
filename_with_file_manager_path
|
||||
from pgadmin.utils.ajax import make_json_response, bad_request, \
|
||||
internal_server_error
|
||||
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
from pgadmin.model import Server, SharedServer
|
||||
@ -129,28 +131,6 @@ def script():
|
||||
)
|
||||
|
||||
|
||||
def filename_with_file_manager_path(_file):
|
||||
"""
|
||||
Args:
|
||||
file: File name returned from client file manager
|
||||
|
||||
Returns:
|
||||
Filename to use for backup with full path taken from preference
|
||||
"""
|
||||
# Set file manager directory from preference
|
||||
storage_dir = get_storage_directory()
|
||||
|
||||
if storage_dir:
|
||||
_file = os.path.join(storage_dir, _file.lstrip('/').lstrip('\\'))
|
||||
elif not os.path.isabs(_file):
|
||||
_file = os.path.join(document_dir(), _file)
|
||||
|
||||
if not os.path.isfile(_file) and not os.path.exists(_file):
|
||||
return None
|
||||
|
||||
return fs_short_path(_file)
|
||||
|
||||
|
||||
def _get_create_req_data():
|
||||
"""
|
||||
Get data from request for create restore job.
|
||||
@ -164,7 +144,7 @@ def _get_create_req_data():
|
||||
try:
|
||||
_file = filename_with_file_manager_path(data['file'])
|
||||
except Exception as e:
|
||||
return True, bad_request(errormsg=str(e)), data
|
||||
return True, internal_server_error(errormsg=str(e)), data, None
|
||||
|
||||
if _file is None:
|
||||
return True, make_json_response(
|
||||
|
@ -260,6 +260,45 @@ def get_complete_file_path(file, validate=True):
|
||||
return file
|
||||
|
||||
|
||||
def filename_with_file_manager_path(_file, create_file=False,
|
||||
skip_permission_check=False):
|
||||
"""
|
||||
Args:
|
||||
file: File name returned from client file manager
|
||||
create_file: Set flag to False when file creation doesn't required
|
||||
Returns:
|
||||
Filename to use for backup with full path taken from preference
|
||||
"""
|
||||
# Set file manager directory from preference
|
||||
storage_dir = get_storage_directory()
|
||||
|
||||
from pgadmin.misc.file_manager import Filemanager
|
||||
Filemanager.check_access_permission(
|
||||
storage_dir, _file, skip_permission_check)
|
||||
if storage_dir:
|
||||
_file = os.path.join(storage_dir, _file.lstrip('/').lstrip('\\'))
|
||||
elif not os.path.isabs(_file):
|
||||
_file = os.path.join(document_dir(), _file)
|
||||
|
||||
def short_filepath():
|
||||
short_path = fs_short_path(_file)
|
||||
# fs_short_path() function may return empty path on Windows
|
||||
# if directory doesn't exists. In that case we strip the last path
|
||||
# component and get the short path.
|
||||
if os.name == 'nt' and short_path == '':
|
||||
base_name = os.path.basename(_file)
|
||||
dir_name = os.path.dirname(_file)
|
||||
short_path = fs_short_path(dir_name) + '\\' + base_name
|
||||
return short_path
|
||||
|
||||
if create_file:
|
||||
# Touch the file to get the short path of the file on windows.
|
||||
with open(_file, 'a'):
|
||||
return short_filepath()
|
||||
|
||||
return short_filepath()
|
||||
|
||||
|
||||
def does_utility_exist(file):
|
||||
"""
|
||||
This function will check the utility file exists on given path.
|
||||
@ -434,27 +473,12 @@ def dump_database_servers(output_file, selected_servers,
|
||||
|
||||
object_dict["Servers"] = server_dict
|
||||
|
||||
# retrieve storage directory path
|
||||
storage_manager_path = None
|
||||
if not from_setup:
|
||||
storage_manager_path = get_storage_directory(user)
|
||||
|
||||
# generate full path of file
|
||||
file_path = unquote(output_file)
|
||||
|
||||
from pgadmin.misc.file_manager import Filemanager
|
||||
try:
|
||||
Filemanager.check_access_permission(storage_manager_path, file_path,
|
||||
from_setup)
|
||||
file_path = filename_with_file_manager_path(
|
||||
unquote(output_file), skip_permission_check=from_setup)
|
||||
except Exception as e:
|
||||
return _handle_error(str(e), from_setup)
|
||||
|
||||
if storage_manager_path is not None:
|
||||
file_path = os.path.join(
|
||||
storage_manager_path,
|
||||
file_path.lstrip('/').lstrip('\\')
|
||||
)
|
||||
|
||||
# write to file
|
||||
file_content = json.dumps(object_dict, indent=4)
|
||||
error_str = "Error: {0}"
|
||||
@ -548,19 +572,12 @@ def load_database_servers(input_file, selected_servers,
|
||||
if user is None:
|
||||
return False, USER_NOT_FOUND % load_user
|
||||
|
||||
# retrieve storage directory path
|
||||
storage_manager_path = None
|
||||
if not from_setup:
|
||||
storage_manager_path = get_storage_directory(user)
|
||||
|
||||
# generate full path of file
|
||||
file_path = unquote(input_file)
|
||||
if storage_manager_path:
|
||||
# generate full path of file
|
||||
file_path = os.path.join(
|
||||
storage_manager_path,
|
||||
file_path.lstrip('/').lstrip('\\')
|
||||
)
|
||||
try:
|
||||
file_path = filename_with_file_manager_path(
|
||||
unquote(input_file), skip_permission_check=from_setup)
|
||||
except Exception as e:
|
||||
return _handle_error(str(e), from_setup)
|
||||
|
||||
try:
|
||||
with open(file_path) as f:
|
||||
|
@ -8517,9 +8517,9 @@ react-checkbox-tree@^1.7.2:
|
||||
nanoid "^3.0.0"
|
||||
prop-types "^15.5.8"
|
||||
|
||||
"react-data-grid@git+https://github.com/EnterpriseDB/react-data-grid.git/#200d2f5e02de694e3e9ffbe177c279bc40240fb8":
|
||||
"react-data-grid@git+https://github.com/pgadmin-org/react-data-grid.git/#200d2f5e02de694e3e9ffbe177c279bc40240fb8":
|
||||
version "7.0.0-beta.14"
|
||||
resolved "git+https://github.com/EnterpriseDB/react-data-grid.git/#200d2f5e02de694e3e9ffbe177c279bc40240fb8"
|
||||
resolved "git+https://github.com/pgadmin-org/react-data-grid.git/#200d2f5e02de694e3e9ffbe177c279bc40240fb8"
|
||||
dependencies:
|
||||
clsx "^1.1.1"
|
||||
|
||||
@ -10337,9 +10337,9 @@ watchpack@^2.4.0:
|
||||
glob-to-regexp "^0.4.1"
|
||||
graceful-fs "^4.1.2"
|
||||
|
||||
"webcabin-docker@git+https://github.com/EnterpriseDB/wcDocker/#3df8aac825ee2892f4d824de273b779cc6dbcad8":
|
||||
"webcabin-docker@git+https://github.com/pgadmin-org/wcdocker/#3df8aac825ee2892f4d824de273b779cc6dbcad8":
|
||||
version "2.2.5"
|
||||
resolved "git+https://github.com/EnterpriseDB/wcDocker/#3df8aac825ee2892f4d824de273b779cc6dbcad8"
|
||||
resolved "git+https://github.com/pgadmin-org/wcdocker/#3df8aac825ee2892f4d824de273b779cc6dbcad8"
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-free" "^5.14.0"
|
||||
FileSaver "^0.10.0"
|
||||
|
Loading…
Reference in New Issue
Block a user