3939import time
4040from stub_sftp import StubSFTPServer
4141from tunnel import Tunneler
42+ import gevent .subprocess
4243
43-
44- logger = logging .getLogger ("fake_server" )
44+ logger = logging .getLogger ("embedded_server" )
4545paramiko_logger = logging .getLogger ('paramiko.transport' )
4646
4747host_key = paramiko .RSAKey (filename = os .path .sep .join ([os .path .dirname (__file__ ), 'rsa.key' ]))
4848
4949class Server (paramiko .ServerInterface ):
50- def __init__ (self , transport , cmd_req_response = {}, fail_auth = False ,
50+ def __init__ (self , transport , fail_auth = False ,
5151 ssh_exception = False ):
5252 self .event = Event ()
53- self .cmd_req_response = cmd_req_response
5453 self .fail_auth = fail_auth
5554 self .ssh_exception = ssh_exception
5655 self .transport = transport
@@ -102,31 +101,18 @@ def check_channel_forward_agent_request(self, channel):
102101
103102 def check_channel_exec_request (self , channel , cmd ):
104103 logger .debug ("Got exec request on channel %s for cmd %s" % (channel , cmd ,))
105- # Remove any 'bash -c' and/or quotes from command
106- cmd = cmd .replace ('bash -c ' , "" )
107- cmd = cmd .replace ('\" ' , "" )
108- cmd = cmd .replace ('\' ' , "" )
109- if not cmd in self .cmd_req_response :
110- return False
111104 self .event .set ()
112- # Check if response is an iterator in which case we
113- # do not return but read from iterator and send responses.
114- # This is to simulate a long running command that has not
115- # finished executing yet.
116- if hasattr (self .cmd_req_response [cmd ], 'next' ):
117- gevent .spawn (self ._long_running_response ,
118- channel , self .cmd_req_response [cmd ])
119- else :
120- channel .send (self .cmd_req_response [cmd ] + os .linesep )
121- channel .send_exit_status (0 )
105+ process = gevent .subprocess .Popen (cmd , stdout = gevent .subprocess .PIPE , shell = True )
106+ gevent .spawn (self ._read_response , channel , process )
122107 return True
123108
124- def _long_running_response (self , channel , responder ):
125- for response in responder :
126- channel .send (response + os .linesep )
127- gevent .sleep (0 )
128- channel .send_exit_status (0 )
129- channel .close ()
109+ def _read_response (self , channel , process ):
110+ for line in process .stdout :
111+ channel .send (line )
112+ process .communicate ()
113+ channel .send_exit_status (process .returncode )
114+ logger .debug ("Command finished with return code %s" , process .returncode )
115+ gevent .sleep (0 )
130116
131117def make_socket (listen_ip , port = 0 ):
132118 """Make socket on given address and available port chosen by OS"""
@@ -140,12 +126,13 @@ def make_socket(listen_ip, port=0):
140126 return
141127 return sock
142128
143- def listen (cmd_req_response , sock , fail_auth = False , ssh_exception = False ,
129+ def listen (sock , fail_auth = False , ssh_exception = False ,
144130 timeout = None ):
145- """Run a fake ssh server and given a cmd_to_run, send given \
146- response to client connection. Returns (server, socket) tuple \
147- where server is a joinable server thread and socket is listening \
148- socket of server."""
131+ """Run server and given a cmd_to_run, send given
132+ response to client connection. Returns (server, socket) tuple
133+ where server is a joinable server thread and socket is listening
134+ socket of server.
135+ """
149136 listen_ip , listen_port = sock .getsockname ()
150137 if not sock :
151138 logger .error ("Could not establish listening connection on %s:%s" , listen_ip , listen_port )
@@ -157,18 +144,18 @@ def listen(cmd_req_response, sock, fail_auth=False, ssh_exception=False,
157144 logger .error ('*** Listen failed: %s' % (str (e ),))
158145 traceback .print_exc ()
159146 return
160- handle_ssh_connection (cmd_req_response , sock , fail_auth = fail_auth ,
147+ handle_ssh_connection (sock , fail_auth = fail_auth ,
161148 timeout = timeout , ssh_exception = ssh_exception )
162149
163- def _handle_ssh_connection (cmd_req_response , transport , fail_auth = False ,
150+ def _handle_ssh_connection (transport , fail_auth = False ,
164151 ssh_exception = False ):
165152 try :
166153 transport .load_server_moduli ()
167154 except :
168155 return
169156 transport .add_server_key (host_key )
170157 transport .set_subsystem_handler ('sftp' , paramiko .SFTPServer , StubSFTPServer )
171- server = Server (transport , cmd_req_response = cmd_req_response ,
158+ server = Server (transport ,
172159 fail_auth = fail_auth , ssh_exception = ssh_exception )
173160 try :
174161 transport .start_server (server = server )
@@ -189,7 +176,7 @@ def _handle_ssh_connection(cmd_req_response, transport, fail_auth=False,
189176 gevent .sleep (.2 )
190177 channel .close ()
191178
192- def handle_ssh_connection (cmd_req_response , sock ,
179+ def handle_ssh_connection (sock ,
193180 fail_auth = False , ssh_exception = False ,
194181 timeout = None ):
195182 conn , addr = sock .accept ()
@@ -200,7 +187,7 @@ def handle_ssh_connection(cmd_req_response, sock,
200187 gevent .Timeout (timeout ).start ()
201188 try :
202189 transport = paramiko .Transport (conn )
203- _handle_ssh_connection (cmd_req_response , transport , fail_auth = fail_auth ,
190+ _handle_ssh_connection (transport , fail_auth = fail_auth ,
204191 ssh_exception = ssh_exception )
205192 except Exception , e :
206193 logger .error ('*** Caught exception: %s: %s' % (str (e .__class__ ), str (e ),))
@@ -211,16 +198,16 @@ def handle_ssh_connection(cmd_req_response, sock,
211198 pass
212199 return
213200
214- def start_server (cmd_req_response , sock , fail_auth = False , ssh_exception = False ,
201+ def start_server (sock , fail_auth = False , ssh_exception = False ,
215202 timeout = None ):
216- return gevent .spawn (listen , cmd_req_response , sock , fail_auth = fail_auth ,
203+ return gevent .spawn (listen , sock , fail_auth = fail_auth ,
217204 timeout = timeout , ssh_exception = ssh_exception )
218205
219206if __name__ == "__main__" :
220207 logging .basicConfig ()
221208 logger .setLevel (logging .DEBUG )
222209 sock = make_socket ('127.0.0.1' )
223- server = start_server ({ 'fake' : 'fake response' }, sock )
210+ server = start_server (sock )
224211 try :
225212 server .join ()
226213 except KeyboardInterrupt :
0 commit comments