1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.scm.provider.git;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.io.Writer;
24 import java.nio.file.FileSystem;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.nio.file.attribute.PosixFilePermissions;
28 import java.security.GeneralSecurityException;
29 import java.security.KeyPair;
30 import java.security.PublicKey;
31 import java.util.ArrayList;
32 import java.util.List;
33
34 import org.apache.maven.scm.provider.git.sshd.git.pack.GitPackCommandFactory;
35 import org.apache.sshd.common.config.keys.KeyUtils;
36 import org.apache.sshd.common.config.keys.writer.openssh.OpenSSHKeyEncryptionContext;
37 import org.apache.sshd.common.config.keys.writer.openssh.OpenSSHKeyPairResourceWriter;
38 import org.apache.sshd.git.GitLocationResolver;
39 import org.apache.sshd.server.SshServer;
40 import org.apache.sshd.server.auth.pubkey.KeySetPublickeyAuthenticator;
41 import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
42 import org.apache.sshd.server.session.ServerSession;
43 import org.apache.sshd.util.test.CommonTestSupportUtils;
44 import org.apache.sshd.util.test.CoreTestSupportUtils;
45 import org.bouncycastle.openssl.PKCS8Generator;
46 import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
47 import org.bouncycastle.openssl.jcajce.JcaPKCS8Generator;
48 import org.bouncycastle.util.io.pem.PemObject;
49
50
51
52
53
54
55
56
57
58
59 public class GitSshServer {
60
61 protected final SshServer sshServer;
62 protected final KeyPair keyPair;
63 protected final List<PublicKey> acceptedPublicKeys;
64
65 public GitSshServer() throws GeneralSecurityException {
66 sshServer = CoreTestSupportUtils.setupTestServer(getClass());
67 keyPair = CommonTestSupportUtils.generateKeyPair(KeyUtils.RSA_ALGORITHM, 2048);
68 acceptedPublicKeys = new ArrayList<>();
69 acceptedPublicKeys.add(keyPair.getPublic());
70 PublickeyAuthenticator authenticator = new KeySetPublickeyAuthenticator("onlykey", acceptedPublicKeys);
71 sshServer.setPublickeyAuthenticator(authenticator);
72 }
73
74
75
76
77
78
79
80
81
82
83
84
85 public void writePrivateKeyAsPkcs8(Path file, String passphrase) throws IOException, GeneralSecurityException {
86
87 if (passphrase != null) {
88
89 OpenSSHKeyPairResourceWriter writer = new OpenSSHKeyPairResourceWriter();
90 OpenSSHKeyEncryptionContext context = new OpenSSHKeyEncryptionContext();
91 context.setCipherType("192");
92 context.setPassword(passphrase);
93 try (OutputStream output = Files.newOutputStream(file)) {
94 writer.writePrivateKey(keyPair, "comment", context, output);
95 }
96 } else {
97
98 PKCS8Generator pkcs8Generator = new JcaPKCS8Generator(keyPair.getPrivate(), null);
99 PemObject pemObject = pkcs8Generator.generate();
100
101 try (Writer writer = Files.newBufferedWriter(file);
102 JcaPEMWriter pw = new JcaPEMWriter(writer)) {
103 pw.writeObject(pemObject);
104 }
105 }
106
107 if (file.getFileSystem().supportedFileAttributeViews().contains("posix")) {
108
109 Files.setPosixFilePermissions(file, PosixFilePermissions.fromString("rwx------"));
110 }
111 }
112
113 public void addPublicKey(PublicKey publicKey) {
114 if (publicKey == null) {
115 throw new IllegalArgumentException("Public key must not be null");
116 }
117 acceptedPublicKeys.add(publicKey);
118 }
119
120 public int getPort() {
121 if (!sshServer.isStarted()) {
122 throw new IllegalStateException("SSH server is not started");
123 }
124 return sshServer.getPort();
125 }
126
127 public void start(Path repositoryRoot) throws IOException {
128 GitLocationResolver gitLocationResolver = new GitLocationResolver() {
129 @Override
130 public Path resolveRootDirectory(String command, String[] args, ServerSession session, FileSystem fs)
131 throws IOException {
132 return repositoryRoot;
133 }
134 };
135
136 sshServer.setCommandFactory(new GitPackCommandFactory(gitLocationResolver));
137 sshServer.start();
138 }
139
140 public void stop() throws IOException {
141 sshServer.stop();
142 }
143 }