d1b5213f6e07c0e6d9ef955963efa6d6d8b5e0a9
[controller.git] / opendaylight / netconf / netconf-ssh / src / main / java / org / opendaylight / controller / netconf / ssh / threads / SocketThread.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.netconf.ssh.threads;
9
10
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;
26
27 @ThreadSafe
28 public class SocketThread implements Runnable, ServerAuthenticationCallback, ServerConnectionCallback
29 {
30
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;
41
42
43     public static void start(Socket socket,
44                              InetSocketAddress clientAddress,
45                              long sessionId,
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();
50     }
51     private SocketThread(Socket socket,
52                          InetSocketAddress clientAddress,
53                          long sessionId,
54                          AuthProvider authProvider) throws IOException {
55
56         this.socket = socket;
57         this.clientAddress = clientAddress;
58         this.sessionId = sessionId;
59         this.remoteAddressWithPort = socket.getRemoteSocketAddress().toString().replaceFirst("/","");
60         this.authProvider = authProvider;
61
62     }
63
64     @Override
65     public void run() {
66         conn = new ServerConnection(socket);
67         try {
68             conn.setPEMHostKey(authProvider.getPEMAsCharArray(),"netconf");
69         } catch (Exception e) {
70             logger.debug("Server authentication setup failed.");
71         }
72         conn.setAuthenticationCallback(this);
73         conn.setServerConnectionCallback(this);
74         try {
75             conn.connect();
76         } catch (IOException e) {
77             logger.error("SocketThread error ",e);
78         }
79     }
80     public ServerSessionCallback acceptSession(final ServerSession session)
81     {
82         SimpleServerSessionCallback cb = new SimpleServerSessionCallback()
83         {
84             @Override
85             public Runnable requestSubsystem(final ServerSession ss, final String subsystem) throws IOException
86             {
87                 return new Runnable(){
88                     public void run()
89                     {
90                         if (subsystem.equals("netconf")){
91                             IOThread netconf_ssh_input = null;
92                             IOThread  netconf_ssh_output = null;
93                             try {
94                                 String hostName = clientAddress.getHostName();
95                                 int portNumber = clientAddress.getPort();
96                                 final Socket echoSocket = new Socket(hostName, portNumber);
97                                 logger.trace("echo socket created");
98
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();
103
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();
109
110                             } catch (Throwable t){
111                                 logger.error("SSH bridge couldn't create echo socket",t.getMessage(),t);
112
113                                 try {
114                                     if (netconf_ssh_input!=null){
115                                         netconf_ssh_input.join();
116                                     }
117                                 } catch (InterruptedException e) {
118                                     Thread.currentThread().interrupt();
119                                    logger.error("netconf_ssh_input join error ",e);
120                                 }
121
122                                 try {
123                                     if (netconf_ssh_output!=null){
124                                         netconf_ssh_output.join();
125                                     }
126                                 } catch (InterruptedException e) {
127                                     Thread.currentThread().interrupt();
128                                     logger.error("netconf_ssh_output join error ",e);
129                                 }
130
131                             }
132                         } else {
133                             try {
134                                 ss.getStdin().write("wrong subsystem requested - closing connection".getBytes());
135                                 ss.close();
136                             } catch (IOException e) {
137                                 logger.debug("excpetion while sending bad subsystem response",e);
138                             }
139                         }
140                     }
141                 };
142             }
143             @Override
144             public Runnable requestPtyReq(final ServerSession ss, final PtySettings pty) throws IOException
145             {
146                 return new Runnable()
147                 {
148                     public void run()
149                     {
150                         //noop
151                     }
152                 };
153             }
154
155             @Override
156             public Runnable requestShell(final ServerSession ss) throws IOException
157             {
158                 return new Runnable()
159                 {
160                     public void run()
161                     {
162                         //noop
163                     }
164                 };
165             }
166         };
167
168         return cb;
169     }
170
171     public String initAuthentication(ServerConnection sc)
172     {
173         logger.trace("Established connection with host {}",remoteAddressWithPort);
174         return "Established connection with host "+remoteAddressWithPort+"\r\n";
175     }
176
177     public String[] getRemainingAuthMethods(ServerConnection sc)
178     {
179         return new String[] { ServerAuthenticationCallback.METHOD_PASSWORD };
180     }
181
182     public AuthenticationResult authenticateWithNone(ServerConnection sc, String username)
183     {
184         return AuthenticationResult.FAILURE;
185     }
186
187     public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password)
188     {
189
190         try {
191             if (authProvider.authenticated(username,password)){
192                 currentUser = username;
193                 logger.trace("user {}@{} authenticated",currentUser,remoteAddressWithPort);
194                 return AuthenticationResult.SUCCESS;
195             }
196         } catch (Exception e){
197             logger.warn("Authentication failed due to :" + e.getLocalizedMessage());
198         }
199         return AuthenticationResult.FAILURE;
200     }
201
202     public AuthenticationResult authenticateWithPublicKey(ServerConnection sc, String username, String algorithm,
203             byte[] publickey, byte[] signature)
204     {
205         return AuthenticationResult.FAILURE;
206     }
207
208 }

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.