Always set interrupted flag when catching InterruptedException.
[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.AuthProvider;
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     private String currentUser;
32     private final String remoteAddressWithPort;
33     private final AuthProvider authProvider;
34
35
36     public static void start(Socket socket,
37                              InetSocketAddress clientAddress,
38                              long sessionId,
39                              AuthProvider authProvider) throws IOException{
40         Thread netconf_ssh_socket_thread = new Thread(new SocketThread(socket,clientAddress,sessionId,authProvider));
41         netconf_ssh_socket_thread.setDaemon(true);
42         netconf_ssh_socket_thread.start();
43     }
44     private SocketThread(Socket socket,
45                          InetSocketAddress clientAddress,
46                          long sessionId,
47                          AuthProvider authProvider) throws IOException {
48
49         this.socket = socket;
50         this.clientAddress = clientAddress;
51         this.sessionId = sessionId;
52         this.remoteAddressWithPort = socket.getRemoteSocketAddress().toString().replaceFirst("/","");
53         this.authProvider = authProvider;
54
55     }
56
57     @Override
58     public void run() {
59         conn = new ServerConnection(socket);
60         try {
61             conn.setPEMHostKey(authProvider.getPEMAsCharArray(),"netconf");
62         } catch (Exception e) {
63             logger.debug("Server authentication setup failed.");
64         }
65         conn.setAuthenticationCallback(this);
66         conn.setServerConnectionCallback(this);
67         try {
68             conn.connect();
69         } catch (IOException e) {
70             logger.error("SocketThread error ",e);
71         }
72     }
73     public ServerSessionCallback acceptSession(final ServerSession session)
74     {
75         SimpleServerSessionCallback cb = new SimpleServerSessionCallback()
76         {
77             @Override
78             public Runnable requestSubsystem(final ServerSession ss, final String subsystem) throws IOException
79             {
80                 return new Runnable(){
81                     public void run()
82                     {
83                         if (subsystem.equals("netconf")){
84                             IOThread netconf_ssh_input = null;
85                             IOThread  netconf_ssh_output = null;
86                             try {
87                                 String hostName = clientAddress.getHostName();
88                                 int portNumber = clientAddress.getPort();
89                                 final Socket echoSocket = new Socket(hostName, portNumber);
90                                 logger.trace("echo socket created");
91
92                                 logger.trace("starting netconf_ssh_input thread");
93                                 netconf_ssh_input =  new IOThread(echoSocket.getInputStream(),ss.getStdin(),"input_thread_"+sessionId,ss,conn);
94                                 netconf_ssh_input.setDaemon(false);
95                                 netconf_ssh_input.start();
96
97                                 logger.trace("starting netconf_ssh_output thread");
98                                 final String customHeader = "["+currentUser+";"+remoteAddressWithPort+";ssh;;;;;;]\n";
99                                 netconf_ssh_output = new IOThread(ss.getStdout(),echoSocket.getOutputStream(),"output_thread_"+sessionId,ss,conn,customHeader);
100                                 netconf_ssh_output.setDaemon(false);
101                                 netconf_ssh_output.start();
102
103                             } catch (Throwable t){
104                                 logger.error("SSH bridge couldn't create echo socket",t.getMessage(),t);
105
106                                 try {
107                                     if (netconf_ssh_input!=null){
108                                         netconf_ssh_input.join();
109                                     }
110                                 } catch (InterruptedException e) {
111                                     Thread.currentThread().interrupt();
112                                    logger.error("netconf_ssh_input join error ",e);
113                                 }
114
115                                 try {
116                                     if (netconf_ssh_output!=null){
117                                         netconf_ssh_output.join();
118                                     }
119                                 } catch (InterruptedException e) {
120                                     Thread.currentThread().interrupt();
121                                     logger.error("netconf_ssh_output join error ",e);
122                                 }
123
124                             }
125                         } else {
126                             try {
127                                 ss.getStdin().write("wrong subsystem requested - closing connection".getBytes());
128                                 ss.close();
129                             } catch (IOException e) {
130                                 logger.debug("excpetion while sending bad subsystem response",e);
131                             }
132                         }
133                     }
134                 };
135             }
136             @Override
137             public Runnable requestPtyReq(final ServerSession ss, final PtySettings pty) throws IOException
138             {
139                 return new Runnable()
140                 {
141                     public void run()
142                     {
143                         //noop
144                     }
145                 };
146             }
147
148             @Override
149             public Runnable requestShell(final ServerSession ss) throws IOException
150             {
151                 return new Runnable()
152                 {
153                     public void run()
154                     {
155                         //noop
156                     }
157                 };
158             }
159         };
160
161         return cb;
162     }
163
164     public String initAuthentication(ServerConnection sc)
165     {
166         logger.trace("Established connection with host {}",remoteAddressWithPort);
167         return "Established connection with host "+remoteAddressWithPort+"\r\n";
168     }
169
170     public String[] getRemainingAuthMethods(ServerConnection sc)
171     {
172         return new String[] { ServerAuthenticationCallback.METHOD_PASSWORD };
173     }
174
175     public AuthenticationResult authenticateWithNone(ServerConnection sc, String username)
176     {
177         return AuthenticationResult.FAILURE;
178     }
179
180     public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password)
181     {
182
183         try {
184             if (authProvider.authenticated(username,password)){
185                 currentUser = username;
186                 logger.trace("user {}@{} authenticated",currentUser,remoteAddressWithPort);
187                 return AuthenticationResult.SUCCESS;
188             }
189         } catch (Exception e){
190             logger.info("Authentication failed due to :" + e.getLocalizedMessage());
191         }
192         return AuthenticationResult.FAILURE;
193     }
194
195     public AuthenticationResult authenticateWithPublicKey(ServerConnection sc, String username, String algorithm,
196             byte[] publickey, byte[] signature)
197     {
198         return AuthenticationResult.FAILURE;
199     }
200
201 }