From 6d984307d485e7ba603f299ac0ca1ab20fd53b73 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Thu, 1 Dec 2016 11:47:56 +0100 Subject: SONAR-8461 WS api/languages/list does escape the parameter "q" --- .../org/sonar/server/language/ws/ListAction.java | 2 +- .../sonar/server/language/ws/LanguageWsTest.java | 27 +++++++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/language/ws/ListAction.java b/server/sonar-server/src/main/java/org/sonar/server/language/ws/ListAction.java index 14edaf7d14b..3ea3e29b015 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/language/ws/ListAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/language/ws/ListAction.java @@ -80,7 +80,7 @@ public class ListAction implements RequestHandler { } private Collection listMatchingLanguages(@Nullable String query, int pageSize) { - Pattern pattern = Pattern.compile(query == null ? MATCH_ALL : MATCH_ALL + query + MATCH_ALL, Pattern.CASE_INSENSITIVE); + Pattern pattern = Pattern.compile(query == null ? MATCH_ALL : MATCH_ALL + Pattern.quote(query) + MATCH_ALL, Pattern.CASE_INSENSITIVE); SortedMap languagesByName = Maps.newTreeMap(); for (Language lang : languages.all()) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/language/ws/LanguageWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/language/ws/LanguageWsTest.java index 1e58a7a2b70..256cdbdf4bd 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/language/ws/LanguageWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/language/ws/LanguageWsTest.java @@ -39,11 +39,12 @@ public class LanguageWsTest { private static final String CONTROLLER_LANGUAGES = "api/languages"; private static final String ACTION_LIST = "list"; + private static final String EMPTY_JSON_RESPONSE = "{\"languages\": []}"; @Mock private Languages languages; - WsTester tester; + private WsTester tester; @Before public void setUp() { @@ -77,7 +78,7 @@ public class LanguageWsTest { } @Test - public void should_list_languages() throws Exception { + public void list_all_languages() throws Exception { tester.newGetRequest(CONTROLLER_LANGUAGES, ACTION_LIST).execute().assertJson(this.getClass(), "list.json"); tester.newGetRequest(CONTROLLER_LANGUAGES, ACTION_LIST) @@ -89,7 +90,10 @@ public class LanguageWsTest { tester.newGetRequest(CONTROLLER_LANGUAGES, ACTION_LIST) .setParam("ps", "10") .execute().assertJson(this.getClass(), "list.json"); + } + @Test + public void filter_languages_by_key_or_name() throws Exception { tester.newGetRequest(CONTROLLER_LANGUAGES, ACTION_LIST) .setParam("q", "ws") .execute().assertJson(this.getClass(), "list_filtered_key.json"); @@ -98,8 +102,25 @@ public class LanguageWsTest { .execute().assertJson(this.getClass(), "list_filtered_name.json"); } + /** + * Potential vulnerability : the query provided by user must + * not be executed as a regexp. + */ + @Test + public void filter_escapes_the_user_query() throws Exception { + // invalid regexp + tester.newGetRequest(CONTROLLER_LANGUAGES, ACTION_LIST) + .setParam("q", "[") + .execute().assertJson(EMPTY_JSON_RESPONSE); + + // do not consider param as a regexp + tester.newGetRequest(CONTROLLER_LANGUAGES, ACTION_LIST) + .setParam("q", ".*") + .execute().assertJson(EMPTY_JSON_RESPONSE); + } + static abstract class TestLanguage extends AbstractLanguage { - public TestLanguage(String key, String language) { + TestLanguage(String key, String language) { super(key, language); } -- cgit v1.2.3 From 7248ea81e7ae41c3d386c424c946a7499eb9acd4 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Thu, 1 Dec 2016 14:09:58 +0100 Subject: SONAR-8462 WS api/rules/repositories does not escape the parameter "q" --- .../sonar/server/rule/ws/RepositoriesAction.java | 2 +- .../server/rule/ws/RepositoriesActionTest.java | 25 +++++++++++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RepositoriesAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RepositoriesAction.java index ac06c0aea8b..4aec9bb14e0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RepositoriesAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RepositoriesAction.java @@ -84,7 +84,7 @@ public class RepositoriesAction implements RulesWsAction { } private Collection listMatchingRepositories(@Nullable String query, @Nullable String languageKey, int pageSize) { - Pattern pattern = Pattern.compile(query == null ? MATCH_ALL : MATCH_ALL + query + MATCH_ALL, Pattern.CASE_INSENSITIVE); + Pattern pattern = Pattern.compile(query == null ? MATCH_ALL : MATCH_ALL + Pattern.quote(query) + MATCH_ALL, Pattern.CASE_INSENSITIVE); SortedMap reposByName = Maps.newTreeMap(); Collection repos = listRepositories(languageKey); diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RepositoriesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RepositoriesActionTest.java index 34d9fd65dd1..ee4aad71f38 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RepositoriesActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RepositoriesActionTest.java @@ -35,6 +35,7 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class RepositoriesActionTest { + private static final String EMPTY_JSON_RESPONSE = "{\"repositories\":[]}"; private WsTester tester; @Mock @@ -65,18 +66,36 @@ public class RepositoriesActionTest { } @Test - public void should_list_repositories() throws Exception { + public void list_repositories() throws Exception { tester = new WsTester(new RulesWs(new RepositoriesAction(repositories))); newRequest().execute().assertJson(this.getClass(), "repositories.json"); newRequest().setParam("language", "xoo").execute().assertJson(this.getClass(), "repositories_xoo.json"); newRequest().setParam("language", "ws").execute().assertJson(this.getClass(), "repositories_ws.json"); + newRequest().setParam("ps", "4").execute().assertJson(this.getClass(), "repositories.json"); + newRequest().setParam("ps", "100").execute().assertJson(this.getClass(), "repositories.json"); + } + + @Test + public void filter_repositories_by_name() throws Exception { + tester = new WsTester(new RulesWs(new RepositoriesAction(repositories))); + newRequest().setParam("q", "common").execute().assertJson(this.getClass(), "repositories_common.json"); newRequest().setParam("q", "squid").execute().assertJson(this.getClass(), "repositories_squid.json"); newRequest().setParam("q", "sonar").execute().assertJson(this.getClass(), "repositories_sonar.json"); newRequest().setParam("q", "sonar").setParam("ps", "2").execute().assertJson(this.getClass(), "repositories_limited.json"); - newRequest().setParam("ps", "4").execute().assertJson(this.getClass(), "repositories.json"); - newRequest().setParam("ps", "100").execute().assertJson(this.getClass(), "repositories.json"); + } + + @Test + public void do_not_consider_query_as_regexp_when_filtering_repositories_by_name() throws Exception { + tester = new WsTester(new RulesWs(new RepositoriesAction(repositories))); + + // invalid regexp : do not fail. Query is not a regexp. + newRequest().setParam("q", "[").execute().assertJson(EMPTY_JSON_RESPONSE); + + // this is not the "match all" regexp + newRequest().setParam("q", ".*").execute().assertJson(EMPTY_JSON_RESPONSE); + } protected TestRequest newRequest() { -- cgit v1.2.3 From 46dc0f0590c60abfe479c95f17f11b552ad070a9 Mon Sep 17 00:00:00 2001 From: Sébastien Lesaint Date: Mon, 5 Dec 2016 17:33:36 +0100 Subject: SONAR-8447 avoid select to key ce_activity.is_key up to date --- sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java index 91f155ee3ca..3893059b645 100644 --- a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java +++ b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java @@ -23,7 +23,6 @@ import com.google.common.base.Optional; import java.util.Collections; import java.util.List; import javax.annotation.Nullable; -import org.apache.ibatis.session.RowBounds; import org.sonar.api.utils.System2; import org.sonar.db.Dao; import org.sonar.db.DbSession; @@ -43,15 +42,13 @@ public class CeActivityDao implements Dao { public void insert(DbSession dbSession, CeActivityDto dto) { dto.setCreatedAt(system2.now()); dto.setUpdatedAt(system2.now()); - dto.setIsLast(false); - mapper(dbSession).insert(dto); + dto.setIsLast(dto.getStatus() != CeActivityDto.Status.CANCELED); - List uuids = mapper(dbSession).selectUuidsOfRecentlyCreatedByIsLastKey(dto.getIsLastKey(), new RowBounds(0, 1)); - // should never be empty, as a row was just inserted! - if (!uuids.isEmpty()) { - mapper(dbSession).updateIsLastToFalseForLastKey(dto.getIsLastKey(), dto.getUpdatedAt()); - mapper(dbSession).updateIsLastToTrueForUuid(uuids.get(0), dto.getUpdatedAt()); + CeActivityMapper ceActivityMapper = mapper(dbSession); + if (dto.getIsLast()) { + ceActivityMapper.updateIsLastToFalseForLastKey(dto.getIsLastKey(), dto.getUpdatedAt()); } + ceActivityMapper.insert(dto); } public List selectOlderThan(DbSession dbSession, long beforeDate) { -- cgit v1.2.3 From af4e544bb6bc2572ddcc37c8597c34b6dd5a35b0 Mon Sep 17 00:00:00 2001 From: Sébastien Lesaint Date: Mon, 5 Dec 2016 17:35:35 +0100 Subject: SONAR-8442 do not do a select to keep ce_activity.is_key up to date --- sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java | 13 +++++-------- .../src/main/java/org/sonar/db/ce/CeActivityMapper.java | 5 ----- .../main/resources/org/sonar/db/ce/CeActivityMapper.xml | 15 --------------- 3 files changed, 5 insertions(+), 28 deletions(-) diff --git a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java index 5a7cada22da..ec07a732ff8 100644 --- a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java +++ b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java @@ -24,7 +24,6 @@ import java.util.Collections; import java.util.List; import java.util.Set; import javax.annotation.Nullable; -import org.apache.ibatis.session.RowBounds; import org.sonar.api.utils.System2; import org.sonar.db.Dao; import org.sonar.db.DbSession; @@ -46,15 +45,13 @@ public class CeActivityDao implements Dao { public void insert(DbSession dbSession, CeActivityDto dto) { dto.setCreatedAt(system2.now()); dto.setUpdatedAt(system2.now()); - dto.setIsLast(false); - mapper(dbSession).insert(dto); + dto.setIsLast(dto.getStatus() != CeActivityDto.Status.CANCELED); - List uuids = mapper(dbSession).selectUuidsOfRecentlyCreatedByIsLastKey(dto.getIsLastKey(), new RowBounds(0, 1)); - // should never be empty, as a row was just inserted! - if (!uuids.isEmpty()) { - mapper(dbSession).updateIsLastToFalseForLastKey(dto.getIsLastKey(), dto.getUpdatedAt()); - mapper(dbSession).updateIsLastToTrueForUuid(uuids.get(0), dto.getUpdatedAt()); + CeActivityMapper ceActivityMapper = mapper(dbSession); + if (dto.getIsLast()) { + ceActivityMapper.updateIsLastToFalseForLastKey(dto.getIsLastKey(), dto.getUpdatedAt()); } + ceActivityMapper.insert(dto); } public List selectOlderThan(DbSession dbSession, long beforeDate) { diff --git a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityMapper.java b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityMapper.java index ea5d9e9c885..07015f5335f 100644 --- a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityMapper.java +++ b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityMapper.java @@ -23,12 +23,9 @@ import java.util.List; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.session.RowBounds; public interface CeActivityMapper { - List selectUuidsOfRecentlyCreatedByIsLastKey(@Param("isLastKey") String isLastKey, RowBounds rowBounds); - @CheckForNull CeActivityDto selectByUuid(@Param("uuid") String uuid); @@ -44,7 +41,5 @@ public interface CeActivityMapper { void updateIsLastToFalseForLastKey(@Param("isLastKey") String isLastKey, @Param("updatedAt") long updatedAt); - void updateIsLastToTrueForUuid(@Param("uuid") String uuid, @Param("updatedAt") long updatedAt); - void deleteByUuids(@Param("uuids") List uuids); } diff --git a/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml b/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml index c0281f1b9d9..c4226b8efb2 100644 --- a/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml +++ b/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml @@ -44,14 +44,6 @@ where ca.uuid=#{uuid} - -