1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.http.test;
12
13 import static org.junit.Assert.assertEquals;
14 import static org.junit.Assert.assertFalse;
15 import static org.junit.Assert.assertTrue;
16 import static org.junit.Assert.fail;
17
18 import java.io.IOException;
19 import java.util.EnumSet;
20 import java.util.List;
21
22 import javax.servlet.DispatcherType;
23 import javax.servlet.Filter;
24 import javax.servlet.FilterChain;
25 import javax.servlet.FilterConfig;
26 import javax.servlet.ServletException;
27 import javax.servlet.ServletRequest;
28 import javax.servlet.ServletResponse;
29 import javax.servlet.http.HttpServletRequest;
30 import javax.servlet.http.HttpServletResponse;
31
32 import org.eclipse.jetty.servlet.FilterHolder;
33 import org.eclipse.jetty.servlet.ServletContextHandler;
34 import org.eclipse.jetty.servlet.ServletHolder;
35 import org.eclipse.jgit.errors.TransportException;
36 import org.eclipse.jgit.errors.UnsupportedCredentialItem;
37 import org.eclipse.jgit.http.server.GitServlet;
38 import org.eclipse.jgit.junit.TestRepository;
39 import org.eclipse.jgit.junit.http.AccessEvent;
40 import org.eclipse.jgit.junit.http.AppServer;
41 import org.eclipse.jgit.lib.ConfigConstants;
42 import org.eclipse.jgit.lib.NullProgressMonitor;
43 import org.eclipse.jgit.lib.Repository;
44 import org.eclipse.jgit.lib.StoredConfig;
45 import org.eclipse.jgit.revwalk.RevBlob;
46 import org.eclipse.jgit.revwalk.RevCommit;
47 import org.eclipse.jgit.transport.CredentialItem;
48 import org.eclipse.jgit.transport.CredentialsProvider;
49 import org.eclipse.jgit.transport.Transport;
50 import org.eclipse.jgit.transport.URIish;
51 import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
52 import org.eclipse.jgit.util.HttpSupport;
53 import org.junit.Before;
54 import org.junit.Test;
55 import org.junit.runner.RunWith;
56 import org.junit.runners.Parameterized;
57
58 @RunWith(Parameterized.class)
59 public class SmartClientSmartServerSslTest extends AllProtocolsHttpTestCase {
60
61
62
63
64
65
66
67
68
69 private CredentialsProvider testCredentials = new CredentialsProvider() {
70
71 @Override
72 public boolean isInteractive() {
73 return false;
74 }
75
76 @Override
77 public boolean supports(CredentialItem... items) {
78 for (CredentialItem item : items) {
79 if (item instanceof CredentialItem.InformationalMessage) {
80 continue;
81 }
82 if (item instanceof CredentialItem.YesNoType) {
83 continue;
84 }
85 return false;
86 }
87 return true;
88 }
89
90 @Override
91 public boolean get(URIish uri, CredentialItem... items)
92 throws UnsupportedCredentialItem {
93 for (CredentialItem item : items) {
94 if (item instanceof CredentialItem.InformationalMessage) {
95 continue;
96 }
97 if (item instanceof CredentialItem.YesNoType) {
98 ((CredentialItem.YesNoType) item).setValue(true);
99 continue;
100 }
101 return false;
102 }
103 return true;
104 }
105 };
106
107 private URIish remoteURI;
108
109 private URIish secureURI;
110
111 private RevBlob A_txt;
112
113 private RevCommit A, B;
114
115 public SmartClientSmartServerSslTest(TestParameters params) {
116 super(params);
117 }
118
119 @Override
120 protected AppServer createServer() {
121 return new AppServer(0, 0);
122 }
123
124 @Override
125 @Before
126 public void setUp() throws Exception {
127 super.setUp();
128
129 final TestRepository<Repository> src = createTestRepository();
130 final String srcName = src.getRepository().getDirectory().getName();
131 StoredConfig cfg = src.getRepository().getConfig();
132 cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
133 ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true);
134 cfg.setInt("protocol", null, "version", enableProtocolV2 ? 2 : 0);
135 cfg.save();
136
137 GitServlet gs = new GitServlet();
138
139 ServletContextHandler app = addNormalContext(gs, src, srcName);
140
141 server.setUp();
142
143 remoteURI = toURIish(app, srcName);
144 secureURI = new URIish(rewriteUrl(remoteURI.toString(), "https",
145 server.getSecurePort()));
146
147 A_txt = src.blob("A");
148 A = src.commit().add("A_txt", A_txt).create();
149 B = src.commit().parent(A).add("A_txt", "C").add("B", "B").create();
150 src.update(master, B);
151
152 src.update("refs/garbage/a/very/long/ref/name/to/compress", B);
153 }
154
155 private ServletContextHandler addNormalContext(GitServlet gs, TestRepository<Repository> src, String srcName) {
156 ServletContextHandler app = server.addContext("/git");
157 app.addFilter(new FilterHolder(new Filter() {
158
159 @Override
160 public void init(FilterConfig filterConfig)
161 throws ServletException {
162
163 }
164
165
166 @Override
167 public void doFilter(ServletRequest request,
168 ServletResponse response, FilterChain chain)
169 throws IOException, ServletException {
170 final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
171 final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
172 final StringBuffer fullUrl = httpServletRequest.getRequestURL();
173 if (httpServletRequest.getQueryString() != null) {
174 fullUrl.append("?")
175 .append(httpServletRequest.getQueryString());
176 }
177 String urlString = rewriteUrl(fullUrl.toString(), "https",
178 server.getSecurePort());
179 httpServletResponse
180 .setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
181 httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
182 urlString.replace("/https/", "/"));
183 }
184
185 @Override
186 public void destroy() {
187
188 }
189 }), "/https/*", EnumSet.of(DispatcherType.REQUEST));
190 app.addFilter(new FilterHolder(new Filter() {
191
192 @Override
193 public void init(FilterConfig filterConfig)
194 throws ServletException {
195
196 }
197
198
199 @Override
200 public void doFilter(ServletRequest request,
201 ServletResponse response, FilterChain chain)
202 throws IOException, ServletException {
203 final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
204 final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
205 final StringBuffer fullUrl = httpServletRequest.getRequestURL();
206 if (httpServletRequest.getQueryString() != null) {
207 fullUrl.append("?")
208 .append(httpServletRequest.getQueryString());
209 }
210 String urlString = rewriteUrl(fullUrl.toString(), "http",
211 server.getPort());
212 httpServletResponse
213 .setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
214 httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
215 urlString.replace("/back/", "/"));
216 }
217
218 @Override
219 public void destroy() {
220
221 }
222 }), "/back/*", EnumSet.of(DispatcherType.REQUEST));
223 gs.setRepositoryResolver(new TestRepositoryResolver(src, srcName));
224 app.addServlet(new ServletHolder(gs), "/*");
225 return app;
226 }
227
228 @Test
229 public void testInitialClone_ViaHttps() throws Exception {
230 Repository dst = createBareRepository();
231 assertFalse(dst.getObjectDatabase().has(A_txt));
232
233 try (Transport t = Transport.open(dst, secureURI)) {
234 t.setCredentialsProvider(testCredentials);
235 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
236 }
237 assertTrue(dst.getObjectDatabase().has(A_txt));
238 assertEquals(B, dst.exactRef(master).getObjectId());
239 fsck(dst, B);
240
241 List<AccessEvent> requests = getRequests();
242 assertEquals(enableProtocolV2 ? 3 : 2, requests.size());
243 }
244
245 @Test
246 public void testInitialClone_RedirectToHttps() throws Exception {
247 Repository dst = createBareRepository();
248 assertFalse(dst.getObjectDatabase().has(A_txt));
249
250 URIish cloneFrom = extendPath(remoteURI, "/https");
251 try (Transport t = Transport.open(dst, cloneFrom)) {
252 t.setCredentialsProvider(testCredentials);
253 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
254 }
255 assertTrue(dst.getObjectDatabase().has(A_txt));
256 assertEquals(B, dst.exactRef(master).getObjectId());
257 fsck(dst, B);
258
259 List<AccessEvent> requests = getRequests();
260 assertEquals(enableProtocolV2 ? 4 : 3, requests.size());
261 }
262
263 @Test
264 public void testInitialClone_RedirectBackToHttp() throws Exception {
265 Repository dst = createBareRepository();
266 assertFalse(dst.getObjectDatabase().has(A_txt));
267
268 URIish cloneFrom = extendPath(secureURI, "/back");
269 try (Transport t = Transport.open(dst, cloneFrom)) {
270 t.setCredentialsProvider(testCredentials);
271 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
272 fail("Should have failed (redirect from https to http)");
273 } catch (TransportException e) {
274 assertTrue(e.getMessage().contains("not allowed"));
275 }
276 }
277
278 @Test
279 public void testInitialClone_SslFailure() throws Exception {
280 Repository dst = createBareRepository();
281 assertFalse(dst.getObjectDatabase().has(A_txt));
282
283 try (Transport t = Transport.open(dst, secureURI)) {
284
285 t.setCredentialsProvider(
286 new UsernamePasswordCredentialsProvider("any", "anypwd"));
287 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
288 fail("Should have failed (SSL certificate not trusted)");
289 } catch (TransportException e) {
290 assertTrue(e.getMessage().contains("Secure connection"));
291 }
292 }
293
294 }