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 package org.eclipse.jgit.transport.ssh;
44
45 import static java.nio.charset.StandardCharsets.UTF_8;
46 import static org.junit.Assert.assertArrayEquals;
47 import static org.junit.Assert.assertEquals;
48 import static org.junit.Assert.assertFalse;
49 import static org.junit.Assert.assertNotNull;
50 import static org.junit.Assert.assertTrue;
51 import static org.junit.Assume.assumeTrue;
52
53 import java.io.File;
54 import java.io.IOException;
55 import java.nio.file.Files;
56 import java.util.List;
57 import java.util.Locale;
58
59 import org.eclipse.jgit.api.errors.TransportException;
60 import org.eclipse.jgit.transport.CredentialItem;
61 import org.eclipse.jgit.transport.JschConfigSessionFactory;
62 import org.junit.Test;
63 import org.junit.experimental.theories.DataPoints;
64 import org.junit.experimental.theories.Theory;
65
66
67
68
69
70
71 public abstract class SshTestBase extends SshTestHarness {
72
73 @DataPoints
74 public static String[] KEY_RESOURCES = {
75 "id_dsa",
76 "id_rsa_1024",
77 "id_rsa_2048",
78 "id_rsa_3072",
79 "id_rsa_4096",
80 "id_ecdsa_256",
81 "id_ecdsa_384",
82 "id_ecdsa_521",
83 "id_ed25519",
84
85 "id_dsa_testpass",
86 "id_rsa_1024_testpass",
87 "id_rsa_2048_testpass",
88 "id_rsa_3072_testpass",
89 "id_rsa_4096_testpass",
90 "id_ecdsa_256_testpass",
91 "id_ecdsa_384_testpass",
92 "id_ecdsa_521_testpass" };
93
94 protected File defaultCloneDir;
95
96 @Override
97 public void setUp() throws Exception {
98 super.setUp();
99 defaultCloneDir = new File(getTemporaryDirectory(), "cloned");
100 }
101
102 @Test(expected = TransportException.class)
103 public void testSshWithoutConfig() throws Exception {
104 cloneWith("ssh://" + TEST_USER + "@localhost:" + testPort
105 + "/doesntmatter", defaultCloneDir, null);
106 }
107
108 @Test
109 public void testSshWithGlobalIdentity() throws Exception {
110 cloneWith(
111 "ssh://" + TEST_USER + "@localhost:" + testPort
112 + "/doesntmatter",
113 defaultCloneDir, null,
114 "IdentityFile " + privateKey1.getAbsolutePath());
115 }
116
117 @Test
118 public void testSshWithDefaultIdentity() throws Exception {
119 File idRsa = new File(privateKey1.getParentFile(), "id_rsa");
120 Files.copy(privateKey1.toPath(), idRsa.toPath());
121
122 cloneWith("ssh://" + TEST_USER + "@localhost:" + testPort
123 + "/doesntmatter", defaultCloneDir, null);
124 }
125
126 @Test
127 public void testSshWithConfig() throws Exception {
128 cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
129 "Host localhost",
130 "HostName localhost",
131 "Port " + testPort,
132 "User " + TEST_USER,
133 "IdentityFile " + privateKey1.getAbsolutePath());
134 }
135
136 @Test
137 public void testSshWithConfigEncryptedUnusedKey() throws Exception {
138
139 File encryptedKey = new File(sshDir, "id_dsa");
140 copyTestResource("id_dsa_testpass", encryptedKey);
141 TestCredentialsProvider provider = new TestCredentialsProvider(
142 "testpass");
143 cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
144 "Host localhost",
145 "HostName localhost",
146 "Port " + testPort,
147 "User " + TEST_USER,
148 "IdentityFile " + privateKey1.getAbsolutePath());
149 assertEquals("CredentialsProvider should not have been called", 0,
150 provider.getLog().size());
151 }
152
153 @Test
154 public void testSshWithConfigEncryptedUnusedKeyInConfigLast()
155 throws Exception {
156
157 File encryptedKey = new File(sshDir, "id_dsa_test_key");
158 copyTestResource("id_dsa_testpass", encryptedKey);
159 TestCredentialsProvider provider = new TestCredentialsProvider(
160 "testpass");
161 cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
162 "Host localhost",
163 "HostName localhost",
164 "Port " + testPort,
165 "User " + TEST_USER,
166 "IdentityFile " + privateKey1.getAbsolutePath(),
167 "IdentityFile " + encryptedKey.getAbsolutePath());
168
169
170 assertEquals("CredentialsProvider should not have been called", 0,
171 provider.getLog().size());
172 }
173
174 @Test
175 public void testSshWithConfigEncryptedUnusedKeyInConfigFirst()
176 throws Exception {
177
178
179
180
181
182 if (getSessionFactory() instanceof JschConfigSessionFactory) {
183 return;
184 }
185
186 File encryptedKey = new File(sshDir, "id_dsa_test_key");
187 copyTestResource("id_dsa_testpass", encryptedKey);
188 TestCredentialsProvider provider = new TestCredentialsProvider(
189 "testpass");
190 cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
191 "Host localhost",
192 "HostName localhost",
193 "Port " + testPort,
194 "User " + TEST_USER,
195 "IdentityFile " + encryptedKey.getAbsolutePath(),
196 "IdentityFile " + privateKey1.getAbsolutePath());
197 assertEquals("CredentialsProvider should have been called once", 1,
198 provider.getLog().size());
199 }
200
201 @Test
202 public void testSshEncryptedUsedKeyCached() throws Exception {
203
204
205 File encryptedKey = new File(sshDir, "id_dsa_test_key");
206 copyTestResource("id_dsa_testpass", encryptedKey);
207 File encryptedPublicKey = new File(sshDir, "id_dsa_test_key.pub");
208 copyTestResource("id_dsa_testpass.pub", encryptedPublicKey);
209 server.setTestUserPublicKey(encryptedPublicKey.toPath());
210 TestCredentialsProvider provider = new TestCredentialsProvider(
211 "testpass");
212 pushTo(provider,
213 cloneWith("ssh://localhost/doesntmatter", //
214 defaultCloneDir, provider,
215 "Host localhost",
216 "HostName localhost",
217 "Port " + testPort,
218 "User " + TEST_USER,
219 "IdentityFile " + encryptedKey.getAbsolutePath()));
220 assertEquals("CredentialsProvider should have been called once", 1,
221 provider.getLog().size());
222 }
223
224 @Test(expected = TransportException.class)
225 public void testSshEncryptedUsedKeyWrongPassword() throws Exception {
226 File encryptedKey = new File(sshDir, "id_dsa_test_key");
227 copyTestResource("id_dsa_testpass", encryptedKey);
228 File encryptedPublicKey = new File(sshDir, "id_dsa_test_key.pub");
229 copyTestResource("id_dsa_testpass.pub", encryptedPublicKey);
230 server.setTestUserPublicKey(encryptedPublicKey.toPath());
231 TestCredentialsProvider provider = new TestCredentialsProvider(
232 "wrongpass");
233 cloneWith("ssh://localhost/doesntmatter", //
234 defaultCloneDir, provider,
235 "Host localhost",
236 "HostName localhost",
237 "Port " + testPort,
238 "User " + TEST_USER,
239 "NumberOfPasswordPrompts 1",
240 "IdentityFile " + encryptedKey.getAbsolutePath());
241 }
242
243 @Test
244 public void testSshEncryptedUsedKeySeveralPassword() throws Exception {
245 File encryptedKey = new File(sshDir, "id_dsa_test_key");
246 copyTestResource("id_dsa_testpass", encryptedKey);
247 File encryptedPublicKey = new File(sshDir, "id_dsa_test_key.pub");
248 copyTestResource("id_dsa_testpass.pub", encryptedPublicKey);
249 server.setTestUserPublicKey(encryptedPublicKey.toPath());
250 TestCredentialsProvider provider = new TestCredentialsProvider(
251 "wrongpass", "wrongpass2", "testpass");
252 cloneWith("ssh://localhost/doesntmatter", //
253 defaultCloneDir, provider,
254 "Host localhost",
255 "HostName localhost",
256 "Port " + testPort,
257 "User " + TEST_USER,
258 "IdentityFile " + encryptedKey.getAbsolutePath());
259 assertEquals("CredentialsProvider should have been called 3 times", 3,
260 provider.getLog().size());
261 }
262
263 @Test(expected = TransportException.class)
264 public void testSshWithoutKnownHosts() throws Exception {
265 assertTrue("Could not delete known_hosts", knownHosts.delete());
266 cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
267 "Host localhost",
268 "HostName localhost",
269 "Port " + testPort,
270 "User " + TEST_USER,
271 "IdentityFile " + privateKey1.getAbsolutePath());
272 }
273
274 @Test
275 public void testSshWithoutKnownHostsWithProviderAsk()
276 throws Exception {
277 File copiedHosts = new File(knownHosts.getParentFile(),
278 "copiedKnownHosts");
279 assertTrue("Failed to rename known_hosts",
280 knownHosts.renameTo(copiedHosts));
281
282
283 TestCredentialsProvider provider = new TestCredentialsProvider();
284 cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
285 "Host localhost",
286 "HostName localhost",
287 "Port " + testPort,
288 "User " + TEST_USER,
289 "IdentityFile " + privateKey1.getAbsolutePath());
290 List<LogEntry> messages = provider.getLog();
291 assertFalse("Expected user interaction", messages.isEmpty());
292 if (getSessionFactory() instanceof JschConfigSessionFactory) {
293
294 assertEquals("Expected to be asked about the key", 1,
295 messages.size());
296 return;
297 }
298 assertEquals(
299 "Expected to be asked about the key, and the file creation",
300 2, messages.size());
301 assertTrue("~/.ssh/known_hosts should exist now", knownHosts.exists());
302
303
304
305 File clonedAgain = new File(getTemporaryDirectory(), "cloned2");
306 cloneWith("ssh://localhost/doesntmatter", clonedAgain, provider, //
307 "Host localhost",
308 "HostName localhost",
309 "Port " + testPort,
310 "User " + TEST_USER,
311 "IdentityFile " + privateKey1.getAbsolutePath());
312 }
313
314 @Test
315 public void testSshWithoutKnownHostsWithProviderAcceptNew()
316 throws Exception {
317 File copiedHosts = new File(knownHosts.getParentFile(),
318 "copiedKnownHosts");
319 assertTrue("Failed to rename known_hosts",
320 knownHosts.renameTo(copiedHosts));
321 TestCredentialsProvider provider = new TestCredentialsProvider();
322 cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
323 "Host localhost",
324 "HostName localhost",
325 "Port " + testPort,
326 "User " + TEST_USER,
327 "StrictHostKeyChecking accept-new",
328 "IdentityFile " + privateKey1.getAbsolutePath());
329 if (getSessionFactory() instanceof JschConfigSessionFactory) {
330
331 assertTrue("CredentialsProvider not called",
332 provider.getLog().isEmpty());
333 return;
334 }
335 assertEquals("Expected to be asked about the file creation", 1,
336 provider.getLog().size());
337 assertTrue("~/.ssh/known_hosts should exist now", knownHosts.exists());
338
339
340
341 File clonedAgain = new File(getTemporaryDirectory(), "cloned2");
342 cloneWith("ssh://localhost/doesntmatter", clonedAgain, null, //
343 "Host localhost",
344 "HostName localhost",
345 "Port " + testPort,
346 "User " + TEST_USER,
347 "IdentityFile " + privateKey1.getAbsolutePath());
348 }
349
350 @Test(expected = TransportException.class)
351 public void testSshWithoutKnownHostsDeny() throws Exception {
352 File copiedHosts = new File(knownHosts.getParentFile(),
353 "copiedKnownHosts");
354 assertTrue("Failed to rename known_hosts",
355 knownHosts.renameTo(copiedHosts));
356 cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
357 "Host localhost",
358 "HostName localhost",
359 "Port " + testPort,
360 "User " + TEST_USER,
361 "StrictHostKeyChecking yes",
362 "IdentityFile " + privateKey1.getAbsolutePath());
363 }
364
365 @Test(expected = TransportException.class)
366 public void testSshModifiedHostKeyDeny()
367 throws Exception {
368 File copiedHosts = new File(knownHosts.getParentFile(),
369 "copiedKnownHosts");
370 assertTrue("Failed to rename known_hosts",
371 knownHosts.renameTo(copiedHosts));
372
373 createKnownHostsFile(knownHosts, "localhost", testPort, publicKey1);
374 cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
375 "Host localhost",
376 "HostName localhost",
377 "Port " + testPort,
378 "User " + TEST_USER,
379 "StrictHostKeyChecking yes",
380 "IdentityFile " + privateKey1.getAbsolutePath());
381 }
382
383 @Test(expected = TransportException.class)
384 public void testSshModifiedHostKeyWithProviderDeny() throws Exception {
385 File copiedHosts = new File(knownHosts.getParentFile(),
386 "copiedKnownHosts");
387 assertTrue("Failed to rename known_hosts",
388 knownHosts.renameTo(copiedHosts));
389
390 createKnownHostsFile(knownHosts, "localhost", testPort, publicKey1);
391 TestCredentialsProvider provider = new TestCredentialsProvider();
392 try {
393 cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
394 "Host localhost",
395 "HostName localhost",
396 "Port " + testPort,
397 "User " + TEST_USER,
398 "StrictHostKeyChecking yes",
399 "IdentityFile " + privateKey1.getAbsolutePath());
400 } catch (Exception e) {
401 assertEquals("Expected to be told about the modified key", 1,
402 provider.getLog().size());
403 assertTrue("Only messages expected", provider.getLog().stream()
404 .flatMap(l -> l.getItems().stream()).allMatch(
405 c -> c instanceof CredentialItem.InformationalMessage));
406 throw e;
407 }
408 }
409
410 private void checkKnownHostsModifiedHostKey(File backup, File newFile,
411 String wrongKey) throws IOException {
412 List<String> oldLines = Files.readAllLines(backup.toPath(), UTF_8);
413
414 String oldKeyPart = null;
415 for (String oldLine : oldLines) {
416 if (oldLine.contains("[localhost]:")) {
417 String[] parts = oldLine.split("\\s+");
418 if (parts.length > 2) {
419 oldKeyPart = parts[parts.length - 2] + ' '
420 + parts[parts.length - 1];
421 break;
422 }
423 }
424 }
425 assertNotNull("Old key not found", oldKeyPart);
426 List<String> newLines = Files.readAllLines(newFile.toPath(), UTF_8);
427 assertFalse("Old host key still found in known_hosts file" + newFile,
428 hasHostKey("localhost", testPort, wrongKey, newLines));
429 assertTrue("New host key not found in known_hosts file" + newFile,
430 hasHostKey("localhost", testPort, oldKeyPart, newLines));
431
432 }
433
434 @Test
435 public void testSshModifiedHostKeyAllow() throws Exception {
436 assertTrue("Failed to delete known_hosts", knownHosts.delete());
437 createKnownHostsFile(knownHosts, "localhost", testPort, publicKey1);
438 File backup = new File(getTemporaryDirectory(), "backupKnownHosts");
439 Files.copy(knownHosts.toPath(), backup.toPath());
440 cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
441 "Host localhost",
442 "HostName localhost",
443 "Port " + testPort,
444 "User " + TEST_USER,
445 "StrictHostKeyChecking no",
446 "IdentityFile " + privateKey1.getAbsolutePath());
447
448 String[] oldLines = Files
449 .readAllLines(backup.toPath(), UTF_8)
450 .toArray(new String[0]);
451 String[] newLines = Files
452 .readAllLines(knownHosts.toPath(), UTF_8)
453 .toArray(new String[0]);
454 assertArrayEquals("Known hosts file should not be modified", oldLines,
455 newLines);
456 }
457
458 @Test
459 public void testSshModifiedHostKeyAsk() throws Exception {
460 File copiedHosts = new File(knownHosts.getParentFile(),
461 "copiedKnownHosts");
462 assertTrue("Failed to rename known_hosts",
463 knownHosts.renameTo(copiedHosts));
464 String wrongKeyPart = createKnownHostsFile(knownHosts, "localhost",
465 testPort, publicKey1);
466 TestCredentialsProvider provider = new TestCredentialsProvider();
467 cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, provider, //
468 "Host localhost",
469 "HostName localhost",
470 "Port " + testPort,
471 "User " + TEST_USER,
472 "IdentityFile " + privateKey1.getAbsolutePath());
473 checkKnownHostsModifiedHostKey(copiedHosts, knownHosts, wrongKeyPart);
474 assertEquals("Expected to be asked about the modified key", 1,
475 provider.getLog().size());
476 }
477
478 @Test
479 public void testSshCloneWithConfigAndPush() throws Exception {
480 pushTo(cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
481 "Host localhost",
482 "HostName localhost",
483 "Port " + testPort,
484 "User " + TEST_USER,
485 "IdentityFile " + privateKey1.getAbsolutePath()));
486 }
487
488 @Test
489 public void testSftpWithConfig() throws Exception {
490 cloneWith("sftp://localhost/.git", defaultCloneDir, null, //
491 "Host localhost",
492 "HostName localhost",
493 "Port " + testPort,
494 "User " + TEST_USER,
495 "IdentityFile " + privateKey1.getAbsolutePath());
496 }
497
498 @Test
499 public void testSftpCloneWithConfigAndPush() throws Exception {
500 pushTo(cloneWith("sftp://localhost/.git", defaultCloneDir, null, //
501 "Host localhost",
502 "HostName localhost",
503 "Port " + testPort,
504 "User " + TEST_USER,
505 "IdentityFile " + privateKey1.getAbsolutePath()));
506 }
507
508 @Test(expected = TransportException.class)
509 public void testSshWithConfigWrongKey() throws Exception {
510 cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
511 "Host localhost",
512 "HostName localhost",
513 "Port " + testPort,
514 "User " + TEST_USER,
515 "IdentityFile " + privateKey2.getAbsolutePath());
516 }
517
518 @Test
519 public void testSshWithWrongUserNameInConfig() throws Exception {
520
521 cloneWith(
522 "ssh://" + TEST_USER + "@localhost:" + testPort
523 + "/doesntmatter",
524 defaultCloneDir, null,
525 "Host localhost",
526 "HostName localhost",
527 "User sombody_else",
528 "IdentityFile " + privateKey1.getAbsolutePath());
529 }
530
531 @Test
532 public void testSshWithWrongPortInConfig() throws Exception {
533
534 cloneWith(
535 "ssh://" + TEST_USER + "@localhost:" + testPort
536 + "/doesntmatter",
537 defaultCloneDir, null,
538 "Host localhost",
539 "HostName localhost",
540 "Port 22",
541 "User " + TEST_USER,
542 "IdentityFile " + privateKey1.getAbsolutePath());
543 }
544
545 @Test
546 public void testSshWithAliasInConfig() throws Exception {
547
548 cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
549 "Host git",
550 "HostName localhost",
551 "Port " + testPort,
552 "User " + TEST_USER,
553 "IdentityFile " + privateKey1.getAbsolutePath(), "",
554 "Host localhost",
555 "HostName localhost",
556 "Port 22",
557 "User someone_else",
558 "IdentityFile " + privateKey2.getAbsolutePath());
559 }
560
561 @Test
562 public void testSshWithUnknownCiphersInConfig() throws Exception {
563
564 cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
565 "Host git",
566 "HostName localhost",
567 "Port " + testPort,
568 "User " + TEST_USER,
569 "IdentityFile " + privateKey1.getAbsolutePath(),
570 "Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr");
571 }
572
573 @Test
574 public void testSshWithUnknownHostKeyAlgorithmsInConfig()
575 throws Exception {
576
577 cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
578 "Host git",
579 "HostName localhost",
580 "Port " + testPort,
581 "User " + TEST_USER,
582 "IdentityFile " + privateKey1.getAbsolutePath(),
583 "HostKeyAlgorithms foobar,ssh-rsa,ssh-dss");
584 }
585
586 @Test
587 public void testSshWithUnknownKexAlgorithmsInConfig()
588 throws Exception {
589
590 cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
591 "Host git",
592 "HostName localhost",
593 "Port " + testPort,
594 "User " + TEST_USER,
595 "IdentityFile " + privateKey1.getAbsolutePath(),
596 "KexAlgorithms foobar,diffie-hellman-group14-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521");
597 }
598
599 @Test
600 public void testSshWithMinimalHostKeyAlgorithmsInConfig()
601 throws Exception {
602
603 cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
604 "Host git",
605 "HostName localhost",
606 "Port " + testPort,
607 "User " + TEST_USER,
608 "IdentityFile " + privateKey1.getAbsolutePath(),
609 "HostKeyAlgorithms ssh-rsa,ssh-dss");
610 }
611
612 @Test
613 public void testSshWithUnknownAuthInConfig() throws Exception {
614 cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
615 "Host git",
616 "HostName localhost",
617 "Port " + testPort,
618 "User " + TEST_USER,
619 "IdentityFile " + privateKey1.getAbsolutePath(),
620 "PreferredAuthentications gssapi-with-mic,hostbased,publickey,keyboard-interactive,password");
621 }
622
623 @Test(expected = TransportException.class)
624 public void testSshWithNoMatchingAuthInConfig() throws Exception {
625
626 cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
627 "Host git",
628 "HostName localhost",
629 "Port " + testPort,
630 "User " + TEST_USER,
631 "IdentityFile " + privateKey1.getAbsolutePath(),
632 "PreferredAuthentications password");
633 }
634
635 @Test
636 public void testRsaHostKeySecond() throws Exception {
637
638
639
640 File newHostKey = new File(getTemporaryDirectory(), "newhostkey");
641 copyTestResource("id_ecdsa_256", newHostKey);
642 server.addHostKey(newHostKey.toPath(), true);
643 cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
644 "Host git",
645 "HostName localhost",
646 "Port " + testPort,
647 "User " + TEST_USER,
648 "IdentityFile " + privateKey1.getAbsolutePath());
649 }
650
651 @Test
652 public void testEcDsaHostKey() throws Exception {
653
654
655
656 File newHostKey = new File(getTemporaryDirectory(), "newhostkey");
657 copyTestResource("id_ecdsa_256", newHostKey);
658 server.addHostKey(newHostKey.toPath(), false);
659 File newHostKeyPub = new File(getTemporaryDirectory(),
660 "newhostkey.pub");
661 copyTestResource("id_ecdsa_256.pub", newHostKeyPub);
662 createKnownHostsFile(knownHosts, "localhost", testPort, newHostKeyPub);
663 cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
664 "Host git",
665 "HostName localhost",
666 "Port " + testPort,
667 "User " + TEST_USER,
668 "IdentityFile " + privateKey1.getAbsolutePath());
669 }
670
671 @Test
672 public void testPasswordAuth() throws Exception {
673 server.enablePasswordAuthentication();
674 TestCredentialsProvider provider = new TestCredentialsProvider(
675 TEST_USER.toUpperCase(Locale.ROOT));
676 cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
677 "Host git",
678 "HostName localhost",
679 "Port " + testPort,
680 "User " + TEST_USER,
681 "PreferredAuthentications password");
682 }
683
684 @Test
685 public void testPasswordAuthSeveralTimes() throws Exception {
686 server.enablePasswordAuthentication();
687 TestCredentialsProvider provider = new TestCredentialsProvider(
688 "wrongpass", "wrongpass", TEST_USER.toUpperCase(Locale.ROOT));
689 cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
690 "Host git",
691 "HostName localhost",
692 "Port " + testPort,
693 "User " + TEST_USER,
694 "PreferredAuthentications password");
695 }
696
697 @Test(expected = TransportException.class)
698 public void testPasswordAuthWrongPassword() throws Exception {
699 server.enablePasswordAuthentication();
700 TestCredentialsProvider provider = new TestCredentialsProvider(
701 "wrongpass");
702 cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
703 "Host git",
704 "HostName localhost",
705 "Port " + testPort,
706 "User " + TEST_USER,
707 "PreferredAuthentications password");
708 }
709
710 @Test(expected = TransportException.class)
711 public void testPasswordAuthNoPassword() throws Exception {
712 server.enablePasswordAuthentication();
713 TestCredentialsProvider provider = new TestCredentialsProvider();
714 cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
715 "Host git",
716 "HostName localhost",
717 "Port " + testPort,
718 "User " + TEST_USER,
719 "PreferredAuthentications password");
720 }
721
722 @Test(expected = TransportException.class)
723 public void testPasswordAuthCorrectPasswordTooLate() throws Exception {
724 server.enablePasswordAuthentication();
725 TestCredentialsProvider provider = new TestCredentialsProvider(
726 "wrongpass", "wrongpass", "wrongpass",
727 TEST_USER.toUpperCase(Locale.ROOT));
728 cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
729 "Host git",
730 "HostName localhost",
731 "Port " + testPort,
732 "User " + TEST_USER,
733 "PreferredAuthentications password");
734 }
735
736 @Test
737 public void testKeyboardInteractiveAuth() throws Exception {
738 server.enableKeyboardInteractiveAuthentication();
739 TestCredentialsProvider provider = new TestCredentialsProvider(
740 TEST_USER.toUpperCase(Locale.ROOT));
741 cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
742 "Host git",
743 "HostName localhost",
744 "Port " + testPort,
745 "User " + TEST_USER,
746 "PreferredAuthentications keyboard-interactive");
747 }
748
749 @Test
750 public void testKeyboardInteractiveAuthSeveralTimes() throws Exception {
751 server.enableKeyboardInteractiveAuthentication();
752 TestCredentialsProvider provider = new TestCredentialsProvider(
753 "wrongpass", "wrongpass", TEST_USER.toUpperCase(Locale.ROOT));
754 cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
755 "Host git",
756 "HostName localhost",
757 "Port " + testPort,
758 "User " + TEST_USER,
759 "PreferredAuthentications keyboard-interactive");
760 }
761
762 @Test(expected = TransportException.class)
763 public void testKeyboardInteractiveAuthWrongPassword() throws Exception {
764 server.enableKeyboardInteractiveAuthentication();
765 TestCredentialsProvider provider = new TestCredentialsProvider(
766 "wrongpass");
767 cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
768 "Host git",
769 "HostName localhost",
770 "Port " + testPort,
771 "User " + TEST_USER,
772 "PreferredAuthentications keyboard-interactive");
773 }
774
775 @Test(expected = TransportException.class)
776 public void testKeyboardInteractiveAuthNoPassword() throws Exception {
777 server.enableKeyboardInteractiveAuthentication();
778 TestCredentialsProvider provider = new TestCredentialsProvider();
779 cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
780 "Host git",
781 "HostName localhost",
782 "Port " + testPort,
783 "User " + TEST_USER,
784 "PreferredAuthentications keyboard-interactive");
785 }
786
787 @Test(expected = TransportException.class)
788 public void testKeyboardInteractiveAuthCorrectPasswordTooLate()
789 throws Exception {
790 server.enableKeyboardInteractiveAuthentication();
791 TestCredentialsProvider provider = new TestCredentialsProvider(
792 "wrongpass", "wrongpass", "wrongpass",
793 TEST_USER.toUpperCase(Locale.ROOT));
794 cloneWith("ssh://git/doesntmatter", defaultCloneDir, provider, //
795 "Host git",
796 "HostName localhost",
797 "Port " + testPort,
798 "User " + TEST_USER,
799 "PreferredAuthentications keyboard-interactive");
800 }
801
802 @Theory
803 public void testSshKeys(String keyName) throws Exception {
804
805
806 assumeTrue(!(getSessionFactory() instanceof JschConfigSessionFactory
807 && (keyName.contains("ed25519")
808 || keyName.startsWith("id_ecdsa_384")
809 || keyName.startsWith("id_ecdsa_521"))));
810 File cloned = new File(getTemporaryDirectory(), "cloned");
811 String keyFileName = keyName + "_key";
812 File privateKey = new File(sshDir, keyFileName);
813 copyTestResource(keyName, privateKey);
814 File publicKey = new File(sshDir, keyFileName + ".pub");
815 copyTestResource(keyName + ".pub", publicKey);
816 server.setTestUserPublicKey(publicKey.toPath());
817 TestCredentialsProvider provider = new TestCredentialsProvider(
818 "testpass");
819 pushTo(provider,
820 cloneWith("ssh://localhost/doesntmatter", //
821 cloned, provider,
822 "Host localhost",
823 "HostName localhost",
824 "Port " + testPort,
825 "User " + TEST_USER,
826 "IdentityFile " + privateKey.getAbsolutePath()));
827 int expectedCalls = keyName.endsWith("testpass") ? 1 : 0;
828 assertEquals("Unexpected calls to CredentialsProvider", expectedCalls,
829 provider.getLog().size());
830
831
832 cloned = new File(getTemporaryDirectory(), "cloned2");
833 pushTo(null,
834 cloneWith("ssh://localhost/doesntmatter", //
835 cloned, null,
836 "Host localhost",
837 "HostName localhost",
838 "Port " + testPort,
839 "User " + TEST_USER,
840 "IdentityFile " + privateKey.getAbsolutePath()));
841 }
842 }