# HG changeset patch # User Marcin Kuzminski # Date 2018-03-28 19:56:23 # Node ID 36dbf06fe692c2583c6d06c31bc00210eee0aacc # Parent 9cdb56f96789469ebb4deef86fa8de028ab72bb1 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. diff --git a/rhodecode/api/tests/test_update_repo.py b/rhodecode/api/tests/test_update_repo.py --- a/rhodecode/api/tests/test_update_repo.py +++ b/rhodecode/api/tests/test_update_repo.py @@ -96,7 +96,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'] diff --git a/rhodecode/api/views/repo_api.py b/rhodecode/api/views/repo_api.py --- a/rhodecode/api/views/repo_api.py +++ b/rhodecode/api/views/repo_api.py @@ -655,6 +655,7 @@ def create_repo( schema = repo_schema.RepoSchema().bind( repo_type_options=rhodecode.BACKENDS.keys(), + repo_type=repo_type, # user caller user=apiuser) @@ -892,16 +893,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'], @@ -1050,6 +1053,7 @@ def fork_repo(request, apiuser, repoid, schema = repo_schema.RepoSchema().bind( repo_type_options=rhodecode.BACKENDS.keys(), + repo_type=repo.repo_type, # user caller user=apiuser) diff --git a/rhodecode/model/validation_schema/schemas/repo_schema.py b/rhodecode/model/validation_schema/schemas/repo_schema.py --- a/rhodecode/model/validation_schema/schemas/repo_schema.py +++ b/rhodecode/model/validation_schema/schemas/repo_schema.py @@ -319,7 +319,7 @@ class RepoSchema(colander.MappingSchema) repo_clone_uri = colander.SchemaNode( colander.String(), - validator=colander.All(colander.Length(min=1)), + validator=deferred_clone_uri_validator, preparers=[preparers.strip_preparer], missing='') diff --git a/rhodecode/model/validation_schema/validators.py b/rhodecode/model/validation_schema/validators.py --- a/rhodecode/model/validation_schema/validators.py +++ b/rhodecode/model/validation_schema/validators.py @@ -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( diff --git a/rhodecode/tests/models/schemas/test_repo_schema.py b/rhodecode/tests/models/schemas/test_repo_schema.py --- a/rhodecode/tests/models/schemas/test_repo_schema.py +++ b/rhodecode/tests/models/schemas/test_repo_schema.py @@ -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 )