]> source.dussan.org Git - sonarqube.git/blob
b27c68a5f1f06c6e2adcd4cbdb12d0e014fba66b
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2022 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 package org.sonar.server.authentication;
22
23 import java.io.IOException;
24 import java.io.PrintWriter;
25 import javax.servlet.FilterChain;
26 import javax.servlet.FilterConfig;
27 import javax.servlet.ServletException;
28 import javax.servlet.http.HttpServletRequest;
29 import javax.servlet.http.HttpServletResponse;
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.mockito.ArgumentCaptor;
33 import org.sonar.api.platform.Server;
34
35 import static org.assertj.core.api.Assertions.assertThat;
36 import static org.junit.Assert.assertThrows;
37 import static org.mockito.ArgumentMatchers.matches;
38 import static org.mockito.Mockito.doReturn;
39 import static org.mockito.Mockito.mock;
40 import static org.mockito.Mockito.verify;
41 import static org.mockito.Mockito.verifyNoInteractions;
42 import static org.mockito.Mockito.when;
43
44 public class SamlValidationRedirectionFilterTest {
45
46   SamlValidationRedirectionFilter underTest;
47
48   @Before
49   public void setup() throws ServletException {
50     Server server = mock(Server.class);
51     doReturn("").when(server).getContextPath();
52     underTest = new SamlValidationRedirectionFilter(server);
53     underTest.init(mock(FilterConfig.class));
54   }
55
56   @Test
57   public void do_get_pattern() {
58     assertThat(underTest.doGetPattern().matches("/oauth2/callback/saml")).isTrue();
59     assertThat(underTest.doGetPattern().matches("/oauth2/callback/")).isFalse();
60     assertThat(underTest.doGetPattern().matches("/oauth2/callback/test")).isFalse();
61     assertThat(underTest.doGetPattern().matches("/oauth2/")).isFalse();
62   }
63
64   @Test
65   public void do_filter_validation_relay_state() throws ServletException, IOException {
66     HttpServletRequest servletRequest = mock(HttpServletRequest.class);
67     HttpServletResponse servletResponse = mock(HttpServletResponse.class);
68     FilterChain filterChain = mock(FilterChain.class);
69
70     String validSample = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
71     when(servletRequest.getParameter(matches("SAMLResponse"))).thenReturn(validSample);
72     when(servletRequest.getParameter(matches("RelayState"))).thenReturn("validation-query");
73     PrintWriter pw = mock(PrintWriter.class);
74     when(servletResponse.getWriter()).thenReturn(pw);
75
76     underTest.doFilter(servletRequest, servletResponse, filterChain);
77
78     verify(servletResponse).setContentType("text/html");
79     ArgumentCaptor<String> htmlProduced = ArgumentCaptor.forClass(String.class);
80     verify(pw).print(htmlProduced.capture());
81     assertThat(htmlProduced.getValue()).contains(validSample);
82   }
83
84   @Test
85   public void do_filter_validation_wrong_SAML_response() throws ServletException, IOException {
86     HttpServletRequest servletRequest = mock(HttpServletRequest.class);
87     HttpServletResponse servletResponse = mock(HttpServletResponse.class);
88     FilterChain filterChain = mock(FilterChain.class);
89
90     String maliciousSaml = "test\"</input><script>/*hack website*/</script><input value=\"";
91
92     when(servletRequest.getParameter(matches("SAMLResponse"))).thenReturn(maliciousSaml);
93     when(servletRequest.getParameter(matches("RelayState"))).thenReturn("validation-query");
94     PrintWriter pw = mock(PrintWriter.class);
95     when(servletResponse.getWriter()).thenReturn(pw);
96
97     underTest.doFilter(servletRequest, servletResponse, filterChain);
98
99     verify(servletResponse).setContentType("text/html");
100     ArgumentCaptor<String> htmlProduced = ArgumentCaptor.forClass(String.class);
101     verify(pw).print(htmlProduced.capture());
102     assertThat(htmlProduced.getValue()).doesNotContain("<script>/*hack website*/</script>");
103     assertThat(htmlProduced.getValue()).contains("action=\"/saml/validation\"");
104   }
105
106   @Test
107   public void do_filter_no_validation_relay_state() throws ServletException, IOException {
108     HttpServletRequest servletRequest = mock(HttpServletRequest.class);
109     HttpServletResponse servletResponse = mock(HttpServletResponse.class);
110     FilterChain filterChain = mock(FilterChain.class);
111
112     doReturn("random_query").when(servletRequest).getParameter("RelayState");
113     underTest.doFilter(servletRequest, servletResponse, filterChain);
114
115     verifyNoInteractions(servletResponse);
116   }
117
118   @Test
119   public void extract_nonexistant_template() {
120     assertThrows(IllegalStateException.class, () -> underTest.extractTemplate("not-there"));
121   }
122 }