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