/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.sshd.git.transport; import java.io.IOException; import java.util.concurrent.TimeUnit; import org.apache.sshd.client.SshClient; import org.apache.sshd.client.channel.ChannelExec; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.common.util.logging.AbstractLoggingBean; import org.eclipse.jgit.transport.CredentialItem; import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.RemoteSession; import org.eclipse.jgit.transport.URIish; import org.eclipse.jgit.util.FS; /** * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a> */ public class GitSshdSession extends AbstractLoggingBean implements RemoteSession { /** * Property used to configure the SSHD {@link org.apache.sshd.common.FactoryManager} with * the default timeout (millis) to connect to the remote SSH server. * If not specified then {@link #DEFAULT_CONNECT_TIMEOUT} is used. */ public static final String CONNECT_TIMEOUT_PROP = "git-ssh-connect-timeout"; public static final long DEFAULT_CONNECT_TIMEOUT = TimeUnit.SECONDS.toMillis(30L); /** * Property used to configure the SSHD {@link org.apache.sshd.common.FactoryManager} with * the default timeout (millis) to authenticate with the remote SSH server. * If not specified then {@link #DEFAULT_AUTH_TIMEOUT} is used. */ public static final String AUTH_TIMEOUT_PROP = "git-ssh-connect-timeout"; public static final long DEFAULT_AUTH_TIMEOUT = TimeUnit.SECONDS.toMillis(15L); /** * Property used to configure the SSHD {@link org.apache.sshd.common.FactoryManager} with * the default timeout (millis) to open a channel to the remote SSH server. * If not specified then {@link #DEFAULT_CHANNEL_OPEN_TIMEOUT} is used. */ public static final String CHANNEL_OPEN_TIMEOUT_PROPT = "git-ssh-channel-open-timeout"; public static final long DEFAULT_CHANNEL_OPEN_TIMEOUT = TimeUnit.SECONDS.toMillis(7L); private final SshClient client; private final ClientSession session; public GitSshdSession(URIish uri, CredentialsProvider credentialsProvider, FS fs, int tms) throws IOException, InterruptedException { String user = uri.getUser(); final String pass = uri.getPass(); String host = uri.getHost(); int port = uri.getPort(); char[] pass2 = null; if (!credentialsProvider.isInteractive()) { CredentialItem.Username usrItem = new CredentialItem.Username(); CredentialItem.Password pwdItem = new CredentialItem.Password(); if (credentialsProvider.get(uri, usrItem, pwdItem)) { if (user == null) { user = usrItem.getValue(); } else if (user.equals(usrItem.getValue())) { pass2 = pwdItem.getValue(); } } } client = createClient(); client.start(); session = client.connect(user, host, port) .verify(client.getLongProperty(CONNECT_TIMEOUT_PROP, DEFAULT_CONNECT_TIMEOUT)) .getSession(); if (log.isDebugEnabled()) { log.debug("Connected to {}:{}", host, port); } if (pass != null) { session.addPasswordIdentity(pass); } if (pass2 != null) { session.addPasswordIdentity(new String(pass2)); } session.auth().verify(session.getLongProperty(AUTH_TIMEOUT_PROP, DEFAULT_AUTH_TIMEOUT)); if (log.isDebugEnabled()) { log.debug("Authenticated: {}", session); } } @Override public Process exec(String commandName, int timeout) throws IOException { if (log.isTraceEnabled()) { log.trace("exec({}) session={}, timeout={} sec.", commandName, session, timeout); } ChannelExec channel = session.createExecChannel(commandName); channel.open().verify(channel.getLongProperty(CHANNEL_OPEN_TIMEOUT_PROPT, DEFAULT_CHANNEL_OPEN_TIMEOUT)); return new GitSshdSessionProcess(channel, commandName, timeout); } @Override public void disconnect() { if (session.isOpen()) { if (log.isDebugEnabled()) { log.debug("Disconnecting from {}", session); } } client.close(true); } protected SshClient createClient() { return SshClient.setUpDefaultClient(); } }