How can i change server directory in python from client? - python

i'm trying to do client-server project. In this project i have to send linux command from client to server. Now i can send some commands like a ls, pwd etc. and they are running correctly and i can read output in client terminal but when i try to send "cd" command, i don't get any error but the directory in server doesn't change. If i use os.chdir(os.path.abspath(data)) command instead of subprocess.check_output , it can change directory but it is useless because i can send a other commands like a ls, pwd , mkdir etc. Thanks for your help
server side:
def threaded(c):
while True:
# data received from client
data = c.recv(1024)
if not data:
print('Bye')
break
try:
data_o = subprocess.check_output(data, shell=True)
except subprocess.CalledProcessError as e:
c.send(b'failed\n')
print(e.output)
if(len(data_o) > 0):
c.send(data_o)
else:
c.send(b'There is no terminal output.')
# connection closed
c.close()
client side:
while True:
# message sent to server
s.send(message.encode('ascii'))
# messaga received from server
data = s.recv(1024)
# print the received message
print('Received from the server :',str(data.decode('ascii')))
# ask the client whether he wants to continue
ans = input('\nDo you want to continue(y/n) :')
if ans == 'y':
message = input("enter message")
continue
else:
break
# close the connection
s.close()

You could check if the command being sent is equal to cd and change the runtime behavior based on that.
data_spl = data.split()
if data_spl[0] == 'cd':
data_o = os.chdir(os.path.abspath(data_spl[1]))
else:
data_o = subprocess.check_output(data, shell=True)

Related

How to take inputs and outputs properly from the same console as a client (connected to a remote server)?

I am currently working on a program in Python that works as a client, and needs to connect remotely to a server using the TCP/IP protocol. After the server receives the client's username, the client can send messages to other clients by typing "#<username> <message>", and this input will be further processed and the message that will be sent to the server will be constructed as "SEND <username> <message>", and this will be actually recognized by the server. Then the server will send back an acknowledgement to the sending client, and the actual message to the destination client.
My approach is to use a main function named chat_run(), used for input and constructing the message that will be sent to the server, and in parallel to run a function named OutputRecvMsg() in a different thread that will receive messages from the server and output them in the console.
The problem is, I want the beginning of all the input lines to start with username >, and the messages received from the server to be output immediately on a new line, and the client to wait for a new input.
My current implementation problem seems to be in receiving messages (the OutputRecvMsg() function). After it outputs a message to the console, I need to press Enter to ask for input, because it remains stuck.
For me, there are two questions regarding the current problem, maybe two threads try to access the same resource (console), maybe I made a mistake regarding the construction of the received message (because I know that sock.recv(4096) is blocking and I tried to avoid a blocking state).
import socket
import time
import re
import threading as th
SERVER_REPLY_1 = 'HELLO'
SERVER_REPLY_2 = 'IN-USE'
AT_SYMBOL = '#'
host_port = ('remote_server_add', 5378)
def build_loggin_msg(msg):
return 'HELLO-FROM ' + msg + ' \n'
def chat_run(sock, currentUser):
while True:
rawInput = input(currentUser + '> ')
if rawInput == '!who':
sock.sendall('WHO\n'.encode())
elif rawInput == '!quit':
sock.close()
break
else:
splittedMsg = re.split(r'\s', rawInput, maxsplit = 1)
if len(splittedMsg) > 1 and splittedMsg[0].startswith(AT_SYMBOL):
userNameToSend = splittedMsg[0][1:]
message = 'SEND ' + userNameToSend + ' ' + splittedMsg[1] + ' \n'
sock.sendall(message.encode())
def OutputRecvMsg(sock, currentUser):
OutMsg =''
chunk = ''
while True:
try:
chunk = sock.recv(4096).decode()
if not chunk:
pass
else:
OutMsg += chunk
except BlockingIOError as e:
if OutMsg:
print(OutMsg)
OutMsg = ''
if __name__ == '__main__':
loggedIn = False
currentUser = None
_data = ''
while not loggedIn:
currentUser = input('Add a username please: ')
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(host_port)
sock.sendall(build_loggin_msg(currentUser).encode())
data = sock.recv(4096).decode()
print(data)
if data.startswith(SERVER_REPLY_1):
loggedIn = True
else:
print('Close connection for retry another username')
sock.close()
time.sleep(1)
sock.setblocking(0)
th.Thread(target=OutputRecvMsg, args=(sock, currentUser)).start()
chat_run(sock, currentUser)
As an example:
Add a username please: Nickname
HELLO Nickname
Nickname> #Nickname hello man -> send to me
Nickname> DELIVERY Nickname hello man
SEND-OK -> here I have to press enter to get the next lines
Nickname>

Python netcat not returning command shell

The code below is meant to copy the features of netcat for instances where netcat is removed from a server but python is not. However, no matter what I try I can't seem to figure out the following problem:
I run the following
./Netcat.py -l -p 9999 -c
followed by
./Netcat.py -t localhost -p 9999
in a separate terminal. I can confirm that, when acting as a server the script does, indeed, receive a connection from the second instance of the script and that it receives data when it is set (upon pressing CTRL+D). However, I then get a hung terminal which does not receive a command prompt back, nor does it have the ability to send more data. I am hoping someone can point out the error at this point.
What should happen is as follows:
spin up server insatance
run script as a client
type some data and close STDIN with CTRL+D at which point the client sends the data to the server
The server should then receive the data and send back a command prompt to the client
The problem is at step 4 and I'm pulling my hair out at this point.
Edit
Having run strace I determined that the client program gets hung up waiting to receive data which I have noted the corresponding line in the code. I do not see why this would be the case.
import sys # used for accessing command line args
import socket # creation of socket objects to listen & send/receive data
import getopt # helps scripts to parse the command line arguments in sys.argv
import concurrent.futures # for running commands in a subshell
import subprocess # The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes.
## Globals ##
listen = False
command = False
target = ""
port = 0
## END GLOBALS ##
def client_sender(buffer):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client.connect((target, port))
if len(buffer):
# bytes([source[, encoding[, errors]]])
client.send(bytes(buffer, 'utf-8'))
# continue sending and receiving data until user kills script
while True:
recv_len = 1
response = ''
while recv_len:
data = client.recv(4096) #<-- PROBLEM
recv_len = len(data)
response += data.decode('utf-8')
if recv_len < 4096:
break
print(response)
buffer = input('#: ')
buffer += '\n'
client.send(buffer)
except socket.error as e:
print('[*] Exception! Exiting')
print(e)
client.close()
def server_loop():
global target
global port
# if no target is defined, listen on all interfaces
if not len(target):
target = '0.0.0.0'
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((target, port))
server.listen(5)
print(f'listening on {target}:{port}')
while True:
client_socket, addr = server.accept()
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
executor.submit(client_handler, client_socket)
def run_command(command):
command = command.rstrip()
# run command & retrieve output
try:
output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
except:
return 'Failed to execute command.\r\n'
def client_handler(client_socket):
global command
# check if shell requested
if command:
while True:
client_socket.send('<BHP:#> ')
# receive until linefeed
cmd_buffer = ''
while '\n' not in cmd_buffer:
cmd_buffer += client_socket.recv(1024)
response = run_command(bufffer)
client_socket.send(response)
def main():
global listen
global port
global command
global target
# make sure the user provided options & arguments
if not len(sys.argv[1:]):
usage()
# parse commandline options
try:
opts, args = getopt.getopt(sys.argv[1:],"lt:p:c", #: succeeds options which expect an argument
['listen', 'target', 'port', 'command'])
except getopt.GetoptError as err:
print(str(err))
usage()
# handle commandline options
for option, argument in opts:
elif option in ('-l', '--listen'):
listen = True
elif option in ('-e', '--execute'):
execute = argument
elif option in ('-c', '--commandshell'):
command = True
elif option in ('-t', '--target'):
target = argument
elif option in ('-p', '--port'):
port = int(argument)
# not listening; sending data from stdin
if not listen and len(target) and port > 0:
buffer = sys.stdin.read()
client_sender(buffer)
if listen:
server_loop()
if __name__ == '__main__':
main()

What can I do with the "Socket Error number 10053"

I started to learn networks and in one of the exercises I was asked
to write a server which response multiple time to the same client
and I got this error
socket.error: [Errno 10053] An established connection was aborted by the software in your host machine
I wanted to ask whether the problem is with the software and not my program, or its with my program.
Here are my server and client (I'm warning that they're pretty long :D)
Server:
import socket
import time
import random
def message_init(client_socket):
"""
this method gets the socket of the client
and waiting for a command from the client
if the command is one of the commands the
server is familiar with, the method returns
a proper message. if its not a known command
to the server, the server sends to the client
'null' in order that it'll enter a new valid
command.
"""
# starting message with 'Garbage' in case when
# the client will insert unsupported commands
message = 'Garbage'
while message == 'Garbage':
# waiting for a command from the client
client_command = client_socket.recv(1024)
length = client_command[0: 2:]
request = client_command[2::]
# message is the proper reply for the request from the client
if request == 'TIME':
# message is the local time
message = time.asctime(time.localtime(time.time()))
elif request == 'NAME':
# message is the name of the server
message = "Daniel's Server"
elif request == 'RAND':
# message is a random integer between 1 - 10
message = str(random.randint(1, 10))
elif request == 'EXIT':
# message is exit and closing the connection with the client
message = 'EXIT'
client_socket.send(message)
client_socket.close()
if request == 'Garbage':
# sending 'null' to the client
# in order that he'll sent a valid command
client_socket.send('null')
# returns a message in proper to the command
return message
def send_message(client_socket, message):
"""
Gets a message and the socket of the client
sending to the client the number of bytes
in the message and afterwards sending the
message itself
"""
new_message = ''
length = len(message)
if length < 10:
new_message += '0'
new_message += str(length) + message
# sending the message to the client
client_socket.send(new_message)
def main():
"""
binding with every client that tries to connect.
getting a command from him, and if the command is
valid, the server does what the command asks for.
The proper Commands:
TIME: returns a string of the local time.
NAME: returns a string of the name of the server.
RAND: returns a string of number between 1 - 10.
EXIT: closing the connection with the client
"""
# creates a new socket
server_socket = socket.socket()
try:
# binding with every client who asks for
server_socket.bind(('0.0.0.0', 1729))
# waiting to get connection from a client
server_socket.listen(1)
except socket.error, e:
print e
connected = False
# an infinite loop of connecting with a client
# getting a command from a client and sending
# him proper response
while True:
if not connected:
# getting the client socket and his address
# and accepting the new connection
(client_socket, client_address) = server_socket.accept()
connected = True
# message gets a valid message using message_init function
message = message_init(client_socket)
if message != 'EXIT':
# if there's still connection:
send_message(client_socket, message)
else:
connected = False
client_socket.close()
# closing the socket of the server
# (although on the current server and client it won't happened)
server_socket.close()
if __name__ == '__main__':
main()`
Client:
import socket
def valid_cmd(command, commands):
"""
getting a command and a list of
approved commands. returning the
command when its one of the commands
"""
while command not in commands:
# waiting until the client enters a valid command
command = raw_input("Please enter one command of the following:"
" TIME, NAME, RAND or EXIT ")
# returns the command if its in commands
return command
def send_request_to_server(my_socket, request):
"""
getting a request and the socket
sending to the server the request
when there is its length before him
in two digits.
for example: 04RAND
04EXIT
"""
length = len(request)
message = ''
# putting a zero before so the length will
# be in two digits form
if length < 10:
message += '0'
message += str(length) + request
# sending the message to the server
my_socket.send(message)
def handle_server_response(my_socket, commands):
"""
Receive the response from the server
and handle it, according to the request
"""
# data gets the response from the server
data = my_socket.recv(1024)
# if the server returned null there was
# a problem with the message so we ask
# from the client to give us other message
while data == 'null':
message = raw_input("Please enter one command of the following:"
"TIME, NAME, RAND or EXIT")
# checks whether the message is valid
message = valid_cmd(message, commands)
# sending the message to the server
send_request_to_server(my_socket, message)
# waiting for the server's response
data = my_socket.recv(1024)
# returns the data when it has valid value
return data
def main():
"""
connecting to the home server
sending it a command
and printing the server's answer
"""
# creating a new socket
my_socket = socket.socket()
try:
# connecting the client to the home server
my_socket.connect(('127.0.0.1', 1729))
except Exception, e:
print e
my_socket.close()
# a list of the approved commands
commands = ['TIME', 'NAME', 'RAND', 'EXIT']
stopped = False
while not stopped:
# asking for an input of command
message = raw_input()
try:
# making sure that message is one of the valid commands
message = valid_cmd(message, commands)
# sending the message to the server
send_request_to_server(my_socket, message)
except Exception, e:
my_socket.close()
print e
# data gets a valid response from the server
data = handle_server_response(my_socket, commands)
# checking it the server disconnected from the client
if data == 'EXIT':
stopped = True
# keeping the length of the upcoming data
# although there is no use for that on that program
length = data[0: 2]
# printing the data from the server
print data[2::]
# disconnecting from the server
my_socket.close()
lst = ['a', 'b', 'c']
assert valid_cmd('b', lst) == 'b', 'valid_cmd should return' \
' the given value if its ' \
'already in the given list'
if __name__ == '__main__':
main()

How to change command line for execution

I wrote a simple code for a chat client and chat server (a separate code for the client and one for the server). My server currently executes with the command line
python chatserve.py <port number>
Just found out that class requirement is that the program starts with the following command line:
./chatclient <portnumber>
How do I convert? I would greatly appreciate any tips/help. Thank you!
(To clarify any confusion, the execution of my chat client also needs a ./chatclient in its command line, but since that part of the code was written in C, I was able to figure out how to get it to execute with specific command lines. I'm not as familiar with Python unfortunately.)
Here is the code:
#!/bin/python
from socket import *
import sys
#initiate chat with client
def chat(connectionsocket, clientname, username):
to_send = ""
while 1: # continue chat until break
# get characters from the user
received = connectionsocket.recv(501)[0:-1]
# if we received nothing, print close message and break
if received == "":
print "Closed connection. Wait for new connection..."
break
# print client username and message
print "{}> {}".format(clientname, received)
# get server input and send to client
to_send = ""
while len(to_send) == 0 or len(to_send) > 500:
to_send = raw_input("{}> ".format(username))
# special "\quit" message
if to_send == "\quit":
print "Closed connection. Wait for new connection..."
break
connectionsocket.send(to_send)
#initiate handshake with client
def handshake(connectionsocket, username):
# get the client username
clientname = connectionsocket.recv(1024)
# send server username to the client
connectionsocket.send(username)
return clientname
#execution
if __name__ == "__main__":
# If wrong number of arguments, print error message and exit
if len(sys.argv) != 2:
print "Error: no port number input"
exit(1)
# get port number and create TCP socket
serverport = sys.argv[1]
serversocket = socket(AF_INET, SOCK_STREAM)
# bind socket to port
serversocket.bind(('', int(serverport)))
# listen on port for incoming messages
serversocket.listen(1)
# get username
username = ""
while len(username) == 0 or len(username) > 10:
username = raw_input("Enter username (10 characters or less): ")
print "Receiving incoming messages..."
# continue receiving incoming messages until close
while 1:
# create new socket for incoming connection
connectionsocket, address = serversocket.accept()
# print connection message
print "Receiving connection on address {}".format(address)
# initiate handshake and chat with incoming connection
chat(connectionsocket, handshake(connectionsocket, username), username)
# close connection
connectionsocket.close()
Follow these steps:
Rename the filename to: chatserve
Add the following command in the first line of your code: #!/usr/bin/python or #!/usr/bin/python2 or #!/usr/bin/python3
Give him permission to execute: chmod +x chatserve

Paramiko recv_ready() returns false values

I am trying to execute a number of commands remotely using paramiko, however the recv_ready() does not return the correct value.
For example after a pwd \n command it will continuously report that the channel is not still ready (obviously false). For some commands it works properly e.g. ls.
Is there something wrong with what I am doing, or is there an issue with paramiko?
import paramiko
import re
import time
def sudo_ssh(hostname, usernameIn, passIn, cmd):
# Create an SSH client
client = paramiko.SSHClient()
# Make sure that we add the remote server's SSH key automatically
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Connect to the client
client.connect(hostname, username=usernameIn, password=passIn)
# Create a raw shell
channel = client.invoke_shell()
# Send the sudo command
for command in cmd:
print("CMD= " + command + "\n")
time.sleep(1)
# wait until channel is ready
while not channel.recv_ready() :
print("NOT READY " + str(channel.recv_ready()) + "\n \n")
time.sleep(1)
# Send the command
channel.send(command)
channel.send("\n")
# Wait a bit, if necessary
time.sleep(1)
# Flush the receive buffer
receive_buffer = channel.recv(4096)
# If promted send the sudo pass
if re.search(b".*\[sudo\].*", receive_buffer):
time.sleep(1)
print(" TYPING SUDO PASSWORD .... \n")
channel.send( "sudoPass" + "\n" )
receive_buffer = channel.recv(4096)
# Print the receive buffer, if necessary
print(receive_buffer)
print("Executed all of the commands. Now will exit \n")
client.close()
com = []
com.append("sudo ls")
com.append("cd /home/user/Downloads")
com.append("sleep 5")
com.append("ls")
com.append("pwd")
com.append("cd /opt/")
sudo_ssh("myhost.com", "user", "pass", com)
The recv_ready method is to check if the data of channel is ready to read or not i.e. data is buffered or not. It doesn't check if channel itself is ready, see - recv_ready().
So you should move the recv_ready() while loop just before the receive_buffer = channel.recv(4096) to make it work.

Categories