/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.uberfire.java.nio.fs.jgit.daemon.ssh;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Collections;
import java.util.Map;
import org.apache.sshd.SshServer;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.PasswordAuthenticator;
import org.apache.sshd.server.command.UnknownCommand;
import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
import org.uberfire.java.nio.fs.jgit.JGitFileSystemProvider;
import org.uberfire.java.nio.security.FileSystemAuthenticator;
import org.uberfire.java.nio.security.FileSystemAuthorizer;
import org.uberfire.java.nio.security.FileSystemUser;
import static org.uberfire.commons.validation.PortablePreconditions.checkNotEmpty;
import static org.uberfire.commons.validation.PortablePreconditions.checkNotNull;
public class GitSSHService {
private final SshServer sshd = SshServer.setUpDefaultServer();
private FileSystemAuthenticator fileSystemAuthenticator;
private FileSystemAuthorizer fileSystemAuthorizer;
public void setup(final File certDir,
final InetSocketAddress inetSocketAddress,
final String sshIdleTimeout,
final String algorithm,
final ReceivePackFactory receivePackFactory,
final JGitFileSystemProvider.RepositoryResolverImpl<BaseGitCommand> repositoryResolver) {
checkNotNull("certDir",
certDir);
checkNotEmpty("sshIdleTimeout",
sshIdleTimeout);
checkNotEmpty("algorithm",
algorithm);
checkNotNull("receivePackFactory",
receivePackFactory);
checkNotNull("repositoryResolver",
repositoryResolver);
sshd.getProperties().put(SshServer.IDLE_TIMEOUT,
sshIdleTimeout);
if (inetSocketAddress != null) {
sshd.setHost(inetSocketAddress.getHostName());
sshd.setPort(inetSocketAddress.getPort());
}
if (!certDir.exists()) {
certDir.mkdirs();
}
final AbstractGeneratorHostKeyProvider keyPairProvider = new SimpleGeneratorHostKeyProvider(new File(certDir,
"hostkey.ser").getAbsolutePath());
try {
SecurityUtils.getKeyPairGenerator(algorithm);
keyPairProvider.setAlgorithm(algorithm);
} catch (final Exception ignore) {
throw new RuntimeException(String.format("Can't use '%s' algorithm for ssh key pair generator.",
algorithm),
ignore);
}
sshd.setKeyPairProvider(keyPairProvider);
sshd.setCommandFactory(new CommandFactory() {
@Override
public Command createCommand(String command) {
if (command.startsWith("git-upload-pack")) {
return new GitUploadCommand(command,
repositoryResolver,
getAuthorizationManager());
} else if (command.startsWith("git-receive-pack")) {
return new GitReceiveCommand(command,
repositoryResolver,
getAuthorizationManager(),
receivePackFactory);
} else {
return new UnknownCommand(command);
}
}
});
sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
@Override
public boolean authenticate(final String username,
final String password,
final ServerSession session) {
FileSystemUser user = getUserPassAuthenticator().authenticate(username,
password);
if (user == null) {
return false;
}
session.setAttribute(BaseGitCommand.SUBJECT_KEY,
user);
return true;
}
});
}
public void stop() {
try {
sshd.stop(true);
} catch (final InterruptedException ignored) {
}
}
public void start() {
try {
sshd.start();
} catch (IOException e) {
throw new RuntimeException("Couldn't start SSH daemon at " + sshd.getHost() + ":" + sshd.getPort(),
e);
}
}
public boolean isRunning() {
return !(sshd.isClosed() || sshd.isClosing());
}
SshServer getSshServer() {
return sshd;
}
public Map<String, String> getProperties() {
return Collections.unmodifiableMap(sshd.getProperties());
}
public FileSystemAuthenticator getUserPassAuthenticator() {
return fileSystemAuthenticator;
}
public void setUserPassAuthenticator(FileSystemAuthenticator fileSystemAuthenticator) {
this.fileSystemAuthenticator = fileSystemAuthenticator;
}
public FileSystemAuthorizer getAuthorizationManager() {
return fileSystemAuthorizer;
}
public void setAuthorizationManager(FileSystemAuthorizer fileSystemAuthorizer) {
this.fileSystemAuthorizer = fileSystemAuthorizer;
}
}