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.sshd.common.config.keys.KeyUtils;
35  import org.apache.sshd.common.config.keys.writer.openssh.OpenSSHKeyEncryptionContext;
36  import org.apache.sshd.common.config.keys.writer.openssh.OpenSSHKeyPairResourceWriter;
37  import org.apache.sshd.git.GitLocationResolver;
38  import org.apache.sshd.git.pack.GitPackCommandFactory;
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         sshServer.setCommandFactory(new GitPackCommandFactory(gitLocationResolver));
136         sshServer.start();
137     }
138 
139     public void stop() throws IOException {
140         sshServer.stop();
141     }
142 }