Merge "Fixed handshake issues with SSH Netconf client"
[controller.git] / opendaylight / netconf / netconf-ssh / src / main / java / org / opendaylight / controller / netconf / ssh / threads / SocketThread.java
1 package org.opendaylight.controller.netconf.ssh.threads;
2
3
4 import ch.ethz.ssh2.AuthenticationResult;
5 import ch.ethz.ssh2.PtySettings;
6 import ch.ethz.ssh2.ServerAuthenticationCallback;
7 import ch.ethz.ssh2.ServerConnection;
8 import ch.ethz.ssh2.ServerConnectionCallback;
9 import ch.ethz.ssh2.ServerSession;
10 import ch.ethz.ssh2.ServerSessionCallback;
11 import ch.ethz.ssh2.SimpleServerSessionCallback;
12 import java.io.IOException;
13 import java.net.InetSocketAddress;
14 import java.net.Socket;
15 import javax.annotation.concurrent.ThreadSafe;
16 import org.opendaylight.controller.netconf.ssh.authentication.RSAKey;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 @ThreadSafe
21 public class SocketThread implements Runnable, ServerAuthenticationCallback, ServerConnectionCallback
22 {
23
24     private Socket socket;
25     private static final String USER = "netconf";
26     private static final String PASSWORD = "netconf";
27     private InetSocketAddress clientAddress;
28     private static final Logger logger =  LoggerFactory.getLogger(SocketThread.class);
29     private ServerConnection conn = null;
30     private long sessionId;
31
32
33     public static void start(Socket socket, InetSocketAddress clientAddress, long sessionId) throws IOException{
34         Thread netconf_ssh_socket_thread = new Thread(new SocketThread(socket,clientAddress,sessionId));
35         netconf_ssh_socket_thread.setDaemon(true);
36         netconf_ssh_socket_thread.start();
37     }
38     private SocketThread(Socket socket, InetSocketAddress clientAddress, long sessionId) throws IOException {
39
40         this.socket = socket;
41         this.clientAddress = clientAddress;
42         this.sessionId = sessionId;
43
44     }
45
46     @Override
47     public void run() {
48         conn = new ServerConnection(socket);
49         RSAKey keyStore = new RSAKey();
50         conn.setRsaHostKey(keyStore.getPrivateKey());
51         conn.setAuthenticationCallback(this);
52         conn.setServerConnectionCallback(this);
53         try {
54             conn.connect();
55         } catch (IOException e) {
56             logger.error("SocketThread error ",e);
57         }
58     }
59     public ServerSessionCallback acceptSession(final ServerSession session)
60     {
61         SimpleServerSessionCallback cb = new SimpleServerSessionCallback()
62         {
63             @Override
64             public Runnable requestSubsystem(final ServerSession ss, final String subsystem) throws IOException
65             {
66                 return new Runnable(){
67                     public void run()
68                     {
69                         if (subsystem.equals("netconf")){
70                             IOThread netconf_ssh_input = null;
71                             IOThread  netconf_ssh_output = null;
72                             try {
73                                 String hostName = clientAddress.getHostName();
74                                 int portNumber = clientAddress.getPort();
75                                 final Socket echoSocket = new Socket(hostName, portNumber);
76                                 logger.trace("echo socket created");
77
78                                 logger.trace("starting netconf_ssh_input thread");
79                                 netconf_ssh_input =  new IOThread(echoSocket.getInputStream(),ss.getStdin(),"input_thread_"+sessionId,ss,conn);
80                                 netconf_ssh_input.setDaemon(false);
81                                 netconf_ssh_input.start();
82
83                                 logger.trace("starting netconf_ssh_output thread");
84                                 netconf_ssh_output = new IOThread(ss.getStdout(),echoSocket.getOutputStream(),"output_thread_"+sessionId,ss,conn);
85                                 netconf_ssh_output.setDaemon(false);
86                                 netconf_ssh_output.start();
87
88                             } catch (Throwable t){
89                                 logger.error(t.getMessage(),t);
90
91                                 try {
92                                     if (netconf_ssh_input!=null){
93                                         netconf_ssh_input.join();
94                                     }
95                                 } catch (InterruptedException e) {
96                                    logger.error("netconf_ssh_input join error ",e);
97                                 }
98
99                                 try {
100                                     if (netconf_ssh_output!=null){
101                                         netconf_ssh_output.join();
102                                     }
103                                 } catch (InterruptedException e) {
104                                     logger.error("netconf_ssh_output join error ",e);
105                                 }
106
107                             }
108                         } else {
109                             try {
110                                 ss.getStdin().write("wrong subsystem requested - closing connection".getBytes());
111                                 ss.close();
112                             } catch (IOException e) {
113                                 logger.debug("excpetion while sending bad subsystem response",e);
114                             }
115                         }
116                     }
117                 };
118             }
119             @Override
120             public Runnable requestPtyReq(final ServerSession ss, final PtySettings pty) throws IOException
121             {
122                 return new Runnable()
123                 {
124                     public void run()
125                     {
126                         //noop
127                     }
128                 };
129             }
130
131             @Override
132             public Runnable requestShell(final ServerSession ss) throws IOException
133             {
134                 return new Runnable()
135                 {
136                     public void run()
137                     {
138                         //noop
139                     }
140                 };
141             }
142         };
143
144         return cb;
145     }
146
147     public String initAuthentication(ServerConnection sc)
148     {
149         return "";
150     }
151
152     public String[] getRemainingAuthMethods(ServerConnection sc)
153     {
154         return new String[] { ServerAuthenticationCallback.METHOD_PASSWORD };
155     }
156
157     public AuthenticationResult authenticateWithNone(ServerConnection sc, String username)
158     {
159         return AuthenticationResult.FAILURE;
160     }
161
162     public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password)
163     {
164         if (USER.equals(username) && PASSWORD.equals(password))
165             return AuthenticationResult.SUCCESS;
166
167         return AuthenticationResult.FAILURE;
168     }
169
170     public AuthenticationResult authenticateWithPublicKey(ServerConnection sc, String username, String algorithm,
171             byte[] publickey, byte[] signature)
172     {
173         return AuthenticationResult.FAILURE;
174     }
175
176 }