2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.netconf.ssh.threads;
11 import ch.ethz.ssh2.AuthenticationResult;
12 import ch.ethz.ssh2.PtySettings;
13 import ch.ethz.ssh2.ServerAuthenticationCallback;
14 import ch.ethz.ssh2.ServerConnection;
15 import ch.ethz.ssh2.ServerConnectionCallback;
16 import ch.ethz.ssh2.ServerSession;
17 import ch.ethz.ssh2.ServerSessionCallback;
18 import ch.ethz.ssh2.SimpleServerSessionCallback;
19 import java.io.IOException;
20 import java.net.InetSocketAddress;
21 import java.net.Socket;
22 import javax.annotation.concurrent.ThreadSafe;
23 import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 public class SocketThread implements Runnable, ServerAuthenticationCallback, ServerConnectionCallback
31 private Socket socket;
32 private static final String USER = "netconf";
33 private static final String PASSWORD = "netconf";
34 private InetSocketAddress clientAddress;
35 private static final Logger logger = LoggerFactory.getLogger(SocketThread.class);
36 private ServerConnection conn = null;
37 private long sessionId;
38 private String currentUser;
39 private final String remoteAddressWithPort;
40 private final AuthProvider authProvider;
43 public static void start(Socket socket,
44 InetSocketAddress clientAddress,
46 AuthProvider authProvider) throws IOException{
47 Thread netconf_ssh_socket_thread = new Thread(new SocketThread(socket,clientAddress,sessionId,authProvider));
48 netconf_ssh_socket_thread.setDaemon(true);
49 netconf_ssh_socket_thread.start();
51 private SocketThread(Socket socket,
52 InetSocketAddress clientAddress,
54 AuthProvider authProvider) throws IOException {
57 this.clientAddress = clientAddress;
58 this.sessionId = sessionId;
59 this.remoteAddressWithPort = socket.getRemoteSocketAddress().toString().replaceFirst("/","");
60 this.authProvider = authProvider;
66 conn = new ServerConnection(socket);
68 conn.setPEMHostKey(authProvider.getPEMAsCharArray(),"netconf");
69 } catch (Exception e) {
70 logger.debug("Server authentication setup failed.");
72 conn.setAuthenticationCallback(this);
73 conn.setServerConnectionCallback(this);
76 } catch (IOException e) {
77 logger.error("SocketThread error ",e);
80 public ServerSessionCallback acceptSession(final ServerSession session)
82 SimpleServerSessionCallback cb = new SimpleServerSessionCallback()
85 public Runnable requestSubsystem(final ServerSession ss, final String subsystem) throws IOException
87 return new Runnable(){
90 if (subsystem.equals("netconf")){
91 IOThread netconf_ssh_input = null;
92 IOThread netconf_ssh_output = null;
94 String hostName = clientAddress.getHostName();
95 int portNumber = clientAddress.getPort();
96 final Socket echoSocket = new Socket(hostName, portNumber);
97 logger.trace("echo socket created");
99 logger.trace("starting netconf_ssh_input thread");
100 netconf_ssh_input = new IOThread(echoSocket.getInputStream(),ss.getStdin(),"input_thread_"+sessionId,ss,conn);
101 netconf_ssh_input.setDaemon(false);
102 netconf_ssh_input.start();
104 logger.trace("starting netconf_ssh_output thread");
105 final String customHeader = "["+currentUser+";"+remoteAddressWithPort+";ssh;;;;;;]\n";
106 netconf_ssh_output = new IOThread(ss.getStdout(),echoSocket.getOutputStream(),"output_thread_"+sessionId,ss,conn,customHeader);
107 netconf_ssh_output.setDaemon(false);
108 netconf_ssh_output.start();
110 } catch (Throwable t){
111 logger.error("SSH bridge couldn't create echo socket",t.getMessage(),t);
114 if (netconf_ssh_input!=null){
115 netconf_ssh_input.join();
117 } catch (InterruptedException e) {
118 Thread.currentThread().interrupt();
119 logger.error("netconf_ssh_input join error ",e);
123 if (netconf_ssh_output!=null){
124 netconf_ssh_output.join();
126 } catch (InterruptedException e) {
127 Thread.currentThread().interrupt();
128 logger.error("netconf_ssh_output join error ",e);
134 ss.getStdin().write("wrong subsystem requested - closing connection".getBytes());
136 } catch (IOException e) {
137 logger.debug("excpetion while sending bad subsystem response",e);
144 public Runnable requestPtyReq(final ServerSession ss, final PtySettings pty) throws IOException
146 return new Runnable()
156 public Runnable requestShell(final ServerSession ss) throws IOException
158 return new Runnable()
171 public String initAuthentication(ServerConnection sc)
173 logger.trace("Established connection with host {}",remoteAddressWithPort);
174 return "Established connection with host "+remoteAddressWithPort+"\r\n";
177 public String[] getRemainingAuthMethods(ServerConnection sc)
179 return new String[] { ServerAuthenticationCallback.METHOD_PASSWORD };
182 public AuthenticationResult authenticateWithNone(ServerConnection sc, String username)
184 return AuthenticationResult.FAILURE;
187 public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password)
191 if (authProvider.authenticated(username,password)){
192 currentUser = username;
193 logger.trace("user {}@{} authenticated",currentUser,remoteAddressWithPort);
194 return AuthenticationResult.SUCCESS;
196 } catch (Exception e){
197 logger.info("Authentication failed due to :" + e.getLocalizedMessage());
199 return AuthenticationResult.FAILURE;
202 public AuthenticationResult authenticateWithPublicKey(ServerConnection sc, String username, String algorithm,
203 byte[] publickey, byte[] signature)
205 return AuthenticationResult.FAILURE;