View Javadoc
1   /*
2    * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  package org.eclipse.jgit.transport;
11  
12  import static org.junit.Assert.assertEquals;
13  
14  import java.io.File;
15  import java.nio.file.Files;
16  import java.util.Arrays;
17  import java.util.concurrent.TimeUnit;
18  
19  import org.eclipse.jgit.junit.MockSystemReader;
20  import org.eclipse.jgit.util.FS;
21  import org.eclipse.jgit.util.SystemReader;
22  import org.junit.After;
23  import org.junit.Before;
24  import org.junit.Test;
25  
26  import com.jcraft.jsch.Session;
27  
28  /**
29   * Tests for correctly interpreting ssh config values when Jsch sessions are
30   * used.
31   */
32  public class JschConfigSessionFactoryTest {
33  
34  	File tmpConfigFile;
35  
36  	OpenSshConfig tmpConfig;
37  
38  	DefaultSshSessionFactory factory = new DefaultSshSessionFactory();
39  
40  	@Before
41  	public void setup() {
42  		SystemReader.setInstance(new MockSystemReader());
43  	}
44  
45  	@After
46  	public void removeTmpConfig() {
47  		SystemReader.setInstance(null);
48  		if (tmpConfigFile == null) {
49  			return;
50  		}
51  		if (tmpConfigFile.exists() && !tmpConfigFile.delete()) {
52  			tmpConfigFile.deleteOnExit();
53  		}
54  		tmpConfigFile = null;
55  	}
56  
57  	@Test
58  	public void testNoConfigEntry() throws Exception {
59  		tmpConfigFile = File.createTempFile("jsch", "test");
60  		tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
61  				tmpConfigFile);
62  		factory.setConfig(tmpConfig);
63  		Session session = createSession("ssh://egit/egit/egit");
64  		assertEquals("egit", session.getHost());
65  		// No user in URI, none in ssh config: default is OS user name
66  		assertEquals(SystemReader.getInstance().getProperty("user.name"),
67  				session.getUserName());
68  		assertEquals(22, session.getPort());
69  	}
70  
71  	@Test
72  	public void testAlias() throws Exception {
73  		tmpConfigFile = createConfig("Host egit", "Hostname git.eclipse.org",
74  				"User foo", "Port 29418");
75  		tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
76  				tmpConfigFile);
77  		factory.setConfig(tmpConfig);
78  		Session session = createSession("ssh://egit/egit/egit");
79  		assertEquals("git.eclipse.org", session.getHost());
80  		assertEquals("foo", session.getUserName());
81  		assertEquals(29418, session.getPort());
82  	}
83  
84  	@Test
85  	public void testAliasWithUser() throws Exception {
86  		tmpConfigFile = createConfig("Host egit", "Hostname git.eclipse.org",
87  				"User foo", "Port 29418");
88  		tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
89  				tmpConfigFile);
90  		factory.setConfig(tmpConfig);
91  		Session session = createSession("ssh://bar@egit/egit/egit");
92  		assertEquals("git.eclipse.org", session.getHost());
93  		assertEquals("bar", session.getUserName());
94  		assertEquals(29418, session.getPort());
95  	}
96  
97  	@Test
98  	public void testAliasWithPort() throws Exception {
99  		tmpConfigFile = createConfig("Host egit", "Hostname git.eclipse.org",
100 				"User foo", "Port 29418");
101 		tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
102 				tmpConfigFile);
103 		factory.setConfig(tmpConfig);
104 		Session session = createSession("ssh://bar@egit:22/egit/egit");
105 		assertEquals("git.eclipse.org", session.getHost());
106 		assertEquals("bar", session.getUserName());
107 		assertEquals(22, session.getPort());
108 	}
109 
110 	@Test
111 	public void testAliasIdentical() throws Exception {
112 		tmpConfigFile = createConfig("Host git.eclipse.org",
113 				"Hostname git.eclipse.org", "User foo", "Port 29418");
114 		tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
115 				tmpConfigFile);
116 		factory.setConfig(tmpConfig);
117 		Session session = createSession("ssh://git.eclipse.org/egit/egit");
118 		assertEquals("git.eclipse.org", session.getHost());
119 		assertEquals("foo", session.getUserName());
120 		assertEquals(29418, session.getPort());
121 	}
122 
123 	@Test
124 	public void testAliasIdenticalWithUser() throws Exception {
125 		tmpConfigFile = createConfig("Host git.eclipse.org",
126 				"Hostname git.eclipse.org", "User foo", "Port 29418");
127 		tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
128 				tmpConfigFile);
129 		factory.setConfig(tmpConfig);
130 		Session session = createSession("ssh://bar@git.eclipse.org/egit/egit");
131 		assertEquals("git.eclipse.org", session.getHost());
132 		assertEquals("bar", session.getUserName());
133 		assertEquals(29418, session.getPort());
134 	}
135 
136 	@Test
137 	public void testAliasIdenticalWithPort() throws Exception {
138 		tmpConfigFile = createConfig("Host git.eclipse.org",
139 				"Hostname git.eclipse.org", "User foo", "Port 29418");
140 		tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
141 				tmpConfigFile);
142 		factory.setConfig(tmpConfig);
143 		Session session = createSession(
144 				"ssh://bar@git.eclipse.org:300/egit/egit");
145 		assertEquals("git.eclipse.org", session.getHost());
146 		assertEquals("bar", session.getUserName());
147 		assertEquals(300, session.getPort());
148 	}
149 
150 	@Test
151 	public void testConnectTimout() throws Exception {
152 		tmpConfigFile = createConfig("Host git.eclipse.org",
153 				"Hostname git.eclipse.org", "User foo", "Port 29418",
154 				"ConnectTimeout 10");
155 		tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
156 				tmpConfigFile);
157 		factory.setConfig(tmpConfig);
158 		Session session = createSession("ssh://git.eclipse.org/something");
159 		assertEquals("git.eclipse.org", session.getHost());
160 		assertEquals("foo", session.getUserName());
161 		assertEquals(29418, session.getPort());
162 		assertEquals(TimeUnit.SECONDS.toMillis(10), session.getTimeout());
163 	}
164 
165 	@Test
166 	public void testAliasCaseDifferenceUpcase() throws Exception {
167 		tmpConfigFile = createConfig("Host Bitbucket.org",
168 				"Hostname bitbucket.org", "User foo", "Port 29418",
169 				"ConnectTimeout 10", //
170 				"Host bitbucket.org", "Hostname bitbucket.org", "User bar",
171 				"Port 22", "ConnectTimeout 5");
172 		tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
173 				tmpConfigFile);
174 		factory.setConfig(tmpConfig);
175 		Session session = createSession("ssh://Bitbucket.org/something");
176 		assertEquals("bitbucket.org", session.getHost());
177 		assertEquals("foo", session.getUserName());
178 		assertEquals(29418, session.getPort());
179 		assertEquals(TimeUnit.SECONDS.toMillis(10), session.getTimeout());
180 	}
181 
182 	@Test
183 	public void testAliasCaseDifferenceLowcase() throws Exception {
184 		tmpConfigFile = createConfig("Host Bitbucket.org",
185 				"Hostname bitbucket.org", "User foo", "Port 29418",
186 				"ConnectTimeout 10", //
187 				"Host bitbucket.org", "Hostname bitbucket.org", "User bar",
188 				"Port 22", "ConnectTimeout 5");
189 		tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
190 				tmpConfigFile);
191 		factory.setConfig(tmpConfig);
192 		Session session = createSession("ssh://bitbucket.org/something");
193 		assertEquals("bitbucket.org", session.getHost());
194 		assertEquals("bar", session.getUserName());
195 		assertEquals(22, session.getPort());
196 		assertEquals(TimeUnit.SECONDS.toMillis(5), session.getTimeout());
197 	}
198 
199 	@Test
200 	public void testAliasCaseDifferenceUpcaseInverted() throws Exception {
201 		tmpConfigFile = createConfig("Host bitbucket.org",
202 				"Hostname bitbucket.org", "User bar", "Port 22",
203 				"ConnectTimeout 5", //
204 				"Host Bitbucket.org", "Hostname bitbucket.org", "User foo",
205 				"Port 29418", "ConnectTimeout 10");
206 		tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
207 				tmpConfigFile);
208 		factory.setConfig(tmpConfig);
209 		Session session = createSession("ssh://Bitbucket.org/something");
210 		assertEquals("bitbucket.org", session.getHost());
211 		assertEquals("foo", session.getUserName());
212 		assertEquals(29418, session.getPort());
213 		assertEquals(TimeUnit.SECONDS.toMillis(10), session.getTimeout());
214 	}
215 
216 	@Test
217 	public void testAliasCaseDifferenceLowcaseInverted() throws Exception {
218 		tmpConfigFile = createConfig("Host bitbucket.org",
219 				"Hostname bitbucket.org", "User bar", "Port 22",
220 				"ConnectTimeout 5", //
221 				"Host Bitbucket.org", "Hostname bitbucket.org", "User foo",
222 				"Port 29418", "ConnectTimeout 10");
223 		tmpConfig = new OpenSshConfig(tmpConfigFile.getParentFile(),
224 				tmpConfigFile);
225 		factory.setConfig(tmpConfig);
226 		Session session = createSession("ssh://bitbucket.org/something");
227 		assertEquals("bitbucket.org", session.getHost());
228 		assertEquals("bar", session.getUserName());
229 		assertEquals(22, session.getPort());
230 		assertEquals(TimeUnit.SECONDS.toMillis(5), session.getTimeout());
231 	}
232 
233 	private File createConfig(String... lines) throws Exception {
234 		File f = File.createTempFile("jsch", "test");
235 		Files.write(f.toPath(), Arrays.asList(lines));
236 		return f;
237 	}
238 
239 	private Session createSession(String uriText) throws Exception {
240 		// For this test to make sense, these few lines must correspond to the
241 		// code in JschConfigSessionFactory.getSession(). Because of
242 		// side-effects we cannot encapsulate that there properly and so we have
243 		// to duplicate this bit here. We also can't test getSession() itself
244 		// since it would try to actually connect to a server.
245 		URIish uri = new URIish(uriText);
246 		String host = uri.getHost();
247 		String user = uri.getUser();
248 		String password = uri.getPass();
249 		int port = uri.getPort();
250 		OpenSshConfig.Host hostConfig = tmpConfig.lookup(host);
251 		if (port <= 0) {
252 			port = hostConfig.getPort();
253 		}
254 		if (user == null) {
255 			user = hostConfig.getUser();
256 		}
257 		return factory.createSession(null, FS.DETECTED, user, password, host,
258 				port, hostConfig);
259 	}
260 }