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.revwalk.RevBlob;
45 import org.eclipse.jgit.revwalk.RevCommit;
46 import org.eclipse.jgit.transport.CredentialItem;
47 import org.eclipse.jgit.transport.CredentialsProvider;
48 import org.eclipse.jgit.transport.Transport;
49 import org.eclipse.jgit.transport.URIish;
50 import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
51 import org.eclipse.jgit.transport.http.HttpConnectionFactory;
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 AllFactoriesHttpTestCase {
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(HttpConnectionFactory cf) {
116 super(cf);
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 src.getRepository()
132 .getConfig()
133 .setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
134 ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true);
135
136 GitServlet gs = new GitServlet();
137
138 ServletContextHandler app = addNormalContext(gs, src, srcName);
139
140 server.setUp();
141
142 remoteURI = toURIish(app, srcName);
143 secureURI = new URIish(rewriteUrl(remoteURI.toString(), "https",
144 server.getSecurePort()));
145
146 A_txt = src.blob("A");
147 A = src.commit().add("A_txt", A_txt).create();
148 B = src.commit().parent(A).add("A_txt", "C").add("B", "B").create();
149 src.update(master, B);
150
151 src.update("refs/garbage/a/very/long/ref/name/to/compress", B);
152 }
153
154 private ServletContextHandler addNormalContext(GitServlet gs, TestRepository<Repository> src, String srcName) {
155 ServletContextHandler app = server.addContext("/git");
156 app.addFilter(new FilterHolder(new Filter() {
157
158 @Override
159 public void init(FilterConfig filterConfig)
160 throws ServletException {
161
162 }
163
164
165 @Override
166 public void doFilter(ServletRequest request,
167 ServletResponse response, FilterChain chain)
168 throws IOException, ServletException {
169 final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
170 final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
171 final StringBuffer fullUrl = httpServletRequest.getRequestURL();
172 if (httpServletRequest.getQueryString() != null) {
173 fullUrl.append("?")
174 .append(httpServletRequest.getQueryString());
175 }
176 String urlString = rewriteUrl(fullUrl.toString(), "https",
177 server.getSecurePort());
178 httpServletResponse
179 .setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
180 httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
181 urlString.replace("/https/", "/"));
182 }
183
184 @Override
185 public void destroy() {
186
187 }
188 }), "/https/*", EnumSet.of(DispatcherType.REQUEST));
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(), "http",
210 server.getPort());
211 httpServletResponse
212 .setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
213 httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
214 urlString.replace("/back/", "/"));
215 }
216
217 @Override
218 public void destroy() {
219
220 }
221 }), "/back/*", EnumSet.of(DispatcherType.REQUEST));
222 gs.setRepositoryResolver(new TestRepositoryResolver(src, srcName));
223 app.addServlet(new ServletHolder(gs), "/*");
224 return app;
225 }
226
227 @Test
228 public void testInitialClone_ViaHttps() throws Exception {
229 Repository dst = createBareRepository();
230 assertFalse(dst.getObjectDatabase().has(A_txt));
231
232 try (Transport t = Transport.open(dst, secureURI)) {
233 t.setCredentialsProvider(testCredentials);
234 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
235 }
236 assertTrue(dst.getObjectDatabase().has(A_txt));
237 assertEquals(B, dst.exactRef(master).getObjectId());
238 fsck(dst, B);
239
240 List<AccessEvent> requests = getRequests();
241 assertEquals(2, requests.size());
242 }
243
244 @Test
245 public void testInitialClone_RedirectToHttps() throws Exception {
246 Repository dst = createBareRepository();
247 assertFalse(dst.getObjectDatabase().has(A_txt));
248
249 URIish cloneFrom = extendPath(remoteURI, "/https");
250 try (Transport t = Transport.open(dst, cloneFrom)) {
251 t.setCredentialsProvider(testCredentials);
252 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
253 }
254 assertTrue(dst.getObjectDatabase().has(A_txt));
255 assertEquals(B, dst.exactRef(master).getObjectId());
256 fsck(dst, B);
257
258 List<AccessEvent> requests = getRequests();
259 assertEquals(3, requests.size());
260 }
261
262 @Test
263 public void testInitialClone_RedirectBackToHttp() throws Exception {
264 Repository dst = createBareRepository();
265 assertFalse(dst.getObjectDatabase().has(A_txt));
266
267 URIish cloneFrom = extendPath(secureURI, "/back");
268 try (Transport t = Transport.open(dst, cloneFrom)) {
269 t.setCredentialsProvider(testCredentials);
270 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
271 fail("Should have failed (redirect from https to http)");
272 } catch (TransportException e) {
273 assertTrue(e.getMessage().contains("not allowed"));
274 }
275 }
276
277 @Test
278 public void testInitialClone_SslFailure() throws Exception {
279 Repository dst = createBareRepository();
280 assertFalse(dst.getObjectDatabase().has(A_txt));
281
282 try (Transport t = Transport.open(dst, secureURI)) {
283
284 t.setCredentialsProvider(
285 new UsernamePasswordCredentialsProvider("any", "anypwd"));
286 t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
287 fail("Should have failed (SSL certificate not trusted)");
288 } catch (TransportException e) {
289 assertTrue(e.getMessage().contains("Secure connection"));
290 }
291 }
292
293 }