#!/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.20130625 # protocol version: 0.2.20130625 # # import sys, os, socket, socketserver, threading, time from include import argparser, comm, auth class ThreadedRequestHandler(socketserver.StreamRequestHandler): def handle(self): """ Handles incoming connections """ # Set time for timeout in seconds self.timeout = TIMEOUT # Print a line with the adress of the connected client if VERBOSITY >=3: print("Client connected: " + str(self.client_address)) # send motd self.request.sendall(bytes((comm.motd(MOTD)), ENCODING)) self.request.sendall(bytes((comm.passwd_request()), ENCODING)) if not auth.check_passwd(self.rfile.readline().strip()): self.request.sendall(bytes((comm.passwd_reply(False)), ENCODING)) return self.request.sendall(bytes((comm.passwd_reply(True)), ENCODING)) repeat = True while repeat: # Receive data self.data = str(self.rfile.readline().strip(), ENCODING) if self.data == "exit": repeat = False # content handler self.request.sendall(bytes( comm.command(str(self.client_address), self.data), ENCODING)) class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): pass def main(): # import global settings global VERBOSITY, HOST, PORT, TIMEOUT, ENCODING, PASSWORD comm.init(ServerVersion, ProtocolVersion, VERBOSITY, aliases, PASSWORD) auth.init(PASSWORD) # parse arguments parser = argparser args = parser.parse(ServerVersion, ProtocolVersion) # hash a given password if args.mkpasswd: import getpass print(auth.mkpasswd(bytes((getpass.getpass().strip()), 'utf-8'))) return # set settings if command line options are given if args.host: HOST = args.host if args.port: PORT = args.port if args.timeout: TIMEOUT = args.timeout if args.encoding: ENCODING = args.encoding if args.verbosity: VERBOSITY = args.verbosity print("aSRC Server\n"\ "Server version: " + ServerVersion + "\n"\ "Protocol version: " + ProtocolVersion + "\n\n"\ "To stop the server, press Ctrl-C\n") # look for pid file if os.path.exists("pid"): # ignore ... if args.delete_pid_file or args.allow_multiple_instances: pass # ... or exit else: print( "\npid file already exists\n"\ "If the server didn't shut down correctly, "\ "just delete this file or pass -n\n"\ "If you want to start multiple instances, pass -m\n") return 1 try: if VERBOSITY >= 1: print("Initializing server...") # Create server server = ThreadedTCPServer((HOST, PORT), ThreadedRequestHandler) if VERBOSITY >= 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() # look for pid file again ... if os.path.exists("pid"): # ... and remove it if -n is given if args.delete_pid_file: os.remove("pid") # write pid file pidf = open("pid", 'w') pidf.write(str(os.getpid())) pidf.close() # do nothing further while True: time.sleep(60) # exit if Ctrl-C is pressed except KeyboardInterrupt: print("\nGot Ctrl-C, shutting down server...") try: server.shutdown() os.remove("pid") 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 VERBOSITY >= 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 - still doesn't work obviously... TIMEOUT = 15 # Encoding to be used when communicating with a client ENCODING = 'utf-8' # SHA512-encoded Password for authentication with the server PASSWORD = '78ddc8555bb1677ff5af75ba5fc02cb30bb592b0610277ae15055e189b77fe3fda496e5027a3d99ec85d54941adee1cc174b50438fdc21d82d0a79f85b58cf44' # 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) VERBOSITY = 3 ############## main()