#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # # asrc-server.py # # Copyright 2012 - 2013 Fanir-Thuban # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # # aSRC (Aliased Server Remote Control) # - SERVER - # # program version: 0.0.0.20130423 # protocol version: 0.2.20130423 # # import sys, os, socket, socketserver, threading, time def motd(): return MOTD def content(client_address, data): ret = "" ret = ret + "{BEGIN}\n"\ "asrcp" + ProtocolVersion + "\n" # Look if the received message is an # valid alias or a predefined command # if it's 'version', return the server and protocol version if data == "version": if DEBUGLEVEL >= 2: print("Got valid service command from" + str(client_address) + ": ", data) ret = ret + "202 Valid Service Command\n"\ "002 Version\n"\ "ServerVersion:" + ServerVersion + "\n"\ "ProtocolVersion:" + ProtocolVersion + "\n" # if it's 'help', give a little help elif data == 'help': if DEBUGLEVEL >= 2: print("Got valid command from" + str(client_address) + ": ", data) # send status code ret = ret + "202 Valid Service Command\n\n" # send the list of aliases ret = ret + "Aviable aliases:\n" for i in aliases.keys(): ret = ret + str(i) + "\n" # if it's a valid userdefined command elif data in aliases: # send status code ret = ret + "201 Valid Command\n\n" # ohmagawd! a debug message!!1! if DEBUGLEVEL >= 2: print("Got valid command from" + str(client_address) + ": ", data) # execute the aliased command g_dict, l_dict = {}, {} exec(str(aliases[data]), g_dict, l_dict) # send may contain data to send to the client if l_dict["send"]: content = str(l_dict["send"]).replace('{', '\{') content = content.replace('}', '\}') ret = ret + content + "\n" # ALL IS LOST!!1! this has to be invalid! else: # send status code ret = ret + "203 Invalid Command\n" if DEBUGLEVEL >= 2: print("Got invalid command from", str(client_address), ": ", data) ret = ret + "{END}\n" return ret class ThreadedRequestHandler(socketserver.StreamRequestHandler): def handle(self): # Set time for timeout in seconds self.timeout = TIMEOUT # Print a line with the adress of the connected client if DEBUGLEVEL >=3: print("Client connected: " + str(self.client_address)) # send header line 1 self.request.sendall(bytes ("asrpc " + ProtocolVersion + "\n", ENCODING)) # send motd self.request.sendall(bytes(motd() + "\n", ENCODING)) # Receive data self.data = str(self.rfile.readline().strip(), ENCODING) # content handler self.request.sendall(bytes( content(str(self.client_address), self.data), ENCODING)) class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): pass def main(): print("aSRC Server\n"\ "Server version: " + ServerVersion + "\n"\ "Protocol version: " + ProtocolVersion + "\n\n"\ "To stop the server, press Ctrl-C\n") try: if DEBUGLEVEL >= 1: print("Initializing server...") # Create server server = ThreadedTCPServer((HOST, PORT), ThreadedRequestHandler) if DEBUGLEVEL >= 1: print("Starting server on", server.server_address[0], "port", server.server_address[1], "...") # Start a thread with the server -- that thread will then start one # more thread for each request ServerThread = threading.Thread(target = server.serve_forever) # Exit the server thread when the main thread terminates ServerThread.daemon = True ServerThread.start() while True: time.sleep(10) except KeyboardInterrupt: print("\nGot Ctrl-C, shutting down server...") try: server.shutdown() except: print("Failed to shutdown server correctly, "\ "socket may be still in use or wasn't even started:", sys.exc_info()) except: print("\nAn error occured:\n", sys.exc_info(), "\n") if DEBUGLEVEL >= 3: input("Press Enter to continue\n") return 0 if __name__ == '__main__': ServerVersion = "0.0.0" ProtocolVersion = "0.2" ############## # SETTINGS # ############## # IP or hostname (use 0.0.0.0 for all interfaces) and port, on which # the server should listen HOST = '127.0.0.1' PORT = 24642 # Timeout of a connection in seconds - obviously still doesn't work... TIMEOUT = 4 # Encoding to be used when communicating with a client ENCODING = 'utf-8' # Dictionary of aliases. Use python syntax. You can use # the variable send for text to send to the client. # # Shell commands can be executed with: # import subprocess # send = subprocess.check_output(["command", "arg", "somemorearg"]) # # You don't have to include sys, os, socket, socketserver, # threading and time, through they are included already. aliases = dict( who = ''' import subprocess send = subprocess.check_output(["whoami"]) ''', where = ''' import subprocess send = subprocess.check_output(["pwd"]) ''', uname = ''' import os send = os.uname() ''', date = ''' import subprocess send = subprocess.check_output(["date"]) ''', ping_fanir = ''' import subprocess send = subprocess.check_output(["ping", "-c 2", "fanir.de"]) ''') # This is sent to the client after the connection is established MOTD = "Welcome! This is only a test server, for developing purposes.\n"\ "Here (may) be more text..." # Verbosity of logging. # Can be from 0 (only default output) to 3 (debug messages) DEBUGLEVEL = 3 ############## main()