api: security, fix problem when absolute paths are specified with API call, that would allow

forking of path based repos if paths are known to end users.
This commit is contained in:
Marcin Kuzminski 2018-03-28 21:56:23 +02:00
parent 15cae89b47
commit 89d8b3cb21
5 changed files with 21 additions and 8 deletions

View file

@ -99,7 +99,9 @@ class TestApiUpdateRepo(object):
id_, params = build_data(
self.apikey, 'update_repo', repoid=repo_name, **updates)
response = api_call(self.app, params)
with mock.patch('rhodecode.model.validation_schema.validators.url_validator'):
response = api_call(self.app, params)
if updates.get('repo_name'):
repo_name = updates['repo_name']

View file

@ -659,6 +659,7 @@ def create_repo(
schema = repo_schema.RepoSchema().bind(
repo_type_options=rhodecode.BACKENDS.keys(),
repo_type=repo_type,
# user caller
user=apiuser)
@ -902,16 +903,18 @@ def update_repo(
request.translate, repo=repo)
old_values = repo.get_api_data()
repo_type = repo.repo_type
schema = repo_schema.RepoSchema().bind(
repo_type_options=rhodecode.BACKENDS.keys(),
repo_ref_options=ref_choices,
repo_type=repo_type,
# user caller
user=apiuser,
old_values=old_values)
try:
schema_data = schema.deserialize(dict(
# we save old value, users cannot change type
repo_type=repo.repo_type,
repo_type=repo_type,
repo_name=updates['repo_name'],
repo_owner=updates['user'],
@ -1062,6 +1065,7 @@ def fork_repo(request, apiuser, repoid, fork_name,
schema = repo_schema.RepoSchema().bind(
repo_type_options=rhodecode.BACKENDS.keys(),
repo_type=repo.repo_type,
# user caller
user=apiuser)

View file

@ -319,13 +319,13 @@ class RepoSchema(colander.MappingSchema):
repo_clone_uri = colander.SchemaNode(
colander.String(),
validator=colander.All(colander.Length(min=1)),
validator=deferred_sync_uri_validator,
preparers=[preparers.strip_preparer],
missing='')
repo_push_uri = colander.SchemaNode(
colander.String(),
validator=colander.All(colander.Length(min=1)),
validator=deferred_sync_uri_validator,
preparers=[preparers.strip_preparer],
missing='')

View file

@ -117,6 +117,11 @@ def url_validator(url, repo_type, config):
% (url, ','.join(allowed_prefixes)))
exc.allowed_prefixes = allowed_prefixes
raise exc
elif repo_type == 'svn':
# no validation for SVN yet
return
raise InvalidCloneUrl('No repo type specified')
class CloneUriValidator(object):
@ -124,16 +129,14 @@ class CloneUriValidator(object):
self.repo_type = repo_type
def __call__(self, node, value):
from rhodecode.lib.utils import make_db_config
try:
config = make_db_config(clear_session=False)
url_validator(value, self.repo_type, config)
except InvalidCloneUrl as e:
log.warning(e)
msg = _(u'Invalid clone url, provide a valid clone '
u'url starting with one of {allowed_prefixes}').format(
allowed_prefixes=e.allowed_prefixes)
raise colander.Invalid(node, msg)
raise colander.Invalid(node, e.message)
except Exception:
log.exception('Url validation failed')
msg = _(u'invalid clone url for {repo_type} repository').format(

View file

@ -53,6 +53,7 @@ class TestRepoSchema(object):
def test_deserialize(self, app, user_admin):
schema = repo_schema.RepoSchema().bind(
repo_type_options=['hg'],
repo_type='hg',
user=user_admin
)
@ -78,6 +79,7 @@ class TestRepoSchema(object):
schema = repo_schema.RepoSchema().bind(
repo_type_options=['hg'],
repo_type='hg',
user=user_admin
)
@ -93,6 +95,7 @@ class TestRepoSchema(object):
def test_deserialize_with_group_name(self, app, user_admin, test_repo_group):
schema = repo_schema.RepoSchema().bind(
repo_type_options=['hg'],
repo_type='hg',
user=user_admin
)
@ -114,6 +117,7 @@ class TestRepoSchema(object):
self, app, user_regular, test_repo_group):
schema = repo_schema.RepoSchema().bind(
repo_type_options=['hg'],
repo_type='hg',
user=user_regular
)