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