From 25d3344104dd95cf2137519f432f6dc789dd207b Mon Sep 17 00:00:00 2001 From: Christian Damken Date: Wed, 19 Jun 2013 16:25:43 +0200 Subject: [PATCH] - inserted more comm.header() and comm.encode_message() - added loop to be able to process multiple commands within one session, send "exit" to exit - added code 004: Exit - added include/auth.py with init() and check_password() - added settings variable PASSWORD (stores a SHA512-encrypted password) - added authenticate() to class comm --- asrc-server.py | 25 +++++++++++------- doc/protocol_reference.odt | Bin 19407 -> 19428 bytes include/__init__.py | 1 + include/auth.py | 23 ++++++++++++++++ include/comm.py | 52 ++++++++++++++++++++++++------------- include/statuscodes.py | 5 ++-- 6 files changed, 77 insertions(+), 29 deletions(-) create mode 100644 include/auth.py diff --git a/asrc-server.py b/asrc-server.py index 7ec77d5..6a29962 100755 --- a/asrc-server.py +++ b/asrc-server.py @@ -25,8 +25,8 @@ # aSRC (Aliased Server Remote Control) # - SERVER - # -# program version: 0.0.0.20130426 -# protocol version: 0.2.20130423 +# program version: 0.0.0.20130617 +# protocol version: 0.2.20130617 # # @@ -53,12 +53,16 @@ class ThreadedRequestHandler(socketserver.StreamRequestHandler): # send motd self.request.sendall(bytes((comm.motd(MOTD) + "\n"), ENCODING)) - # Receive data - self.data = str(self.rfile.readline().strip(), ENCODING) + repeat = True - # content handler - self.request.sendall(bytes( - comm.command(str(self.client_address), self.data), ENCODING)) + 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): @@ -67,10 +71,10 @@ class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): def main(): # import global settings - global VERBOSITY, HOST, PORT, TIMEOUT, ENCODING + global VERBOSITY, HOST, PORT, TIMEOUT, ENCODING, PASSWORD - comm.init(ServerVersion, ProtocolVersion, VERBOSITY, aliases) + comm.init(ServerVersion, ProtocolVersion, VERBOSITY, aliases, PASSWORD) # parse arguments parser = argparser @@ -170,6 +174,9 @@ if __name__ == '__main__': # Encoding to be used when communicating with a client ENCODING = 'utf-8' + # SHA512-encoded Password for authentication with the server + PASSWORD = 'a52fb4e552326fd8216f52a96f3d037309ef25acb22e5ead60bf258d2ea6652ab9fd5ab1117eb4bafe7476224d081ad7737132c4c096e9e8287a3c3f9d7d14f6' + # Dictionary of aliases. Use python syntax. You can use # the variable send for text to send to the client. # diff --git a/doc/protocol_reference.odt b/doc/protocol_reference.odt index fa01699aa3ed6bcccd2164483686267455a4e9aa..b98d685aff546144ba5b64f54e19e2f71b3ba065 100644 GIT binary patch delta 13846 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 delta 13864 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 Vm>lVZF=@ht5k)KnOxdU1{vUeSHwXX# diff --git a/include/__init__.py b/include/__init__.py index c891f96..02d3aa8 100644 --- a/include/__init__.py +++ b/include/__init__.py @@ -1,3 +1,4 @@ from .argparser import argparser +from .auth import auth from .comm import comm from .statuscodes import statuscodes diff --git a/include/auth.py b/include/auth.py new file mode 100644 index 0000000..73712ed --- /dev/null +++ b/include/auth.py @@ -0,0 +1,23 @@ +# includes/auth.py +# +# module version: 0.0.20130617 +# for protocol version 0.2.20130617 +# + +class auth: + passwd = "" + + def init(password): + #from Crypto.Hash import Hash + import hashlib + + global passwd + passwd = password + + + def check_passwd(incpass): + """ + checks a given password + """ + if hashlib.sha512(bytearray(incpass)).hexdigest() == passwd: return True + else: return False diff --git a/include/comm.py b/include/comm.py index 52cc7ad..20a4754 100644 --- a/include/comm.py +++ b/include/comm.py @@ -1,11 +1,12 @@ # includes/comm.py # -# module version: 0.0.20130426 -# for protocol versions 0.2.20130423 and later +# module version: 0.0.20130617 +# for protocol version 0.2.20130617 # from .statuscodes import statuscodes +from .auth import auth class comm: @@ -16,16 +17,22 @@ class comm: protocol_version = "" verbosity = 0 + # initializes global settings - def init(ServerVersion, ProtocolVersion, Verbosity, Aliases): + def init(ServerVersion, ProtocolVersion, Verbosity, Aliases, Password): """ - makes settings aviable in this class + makes settings aviable in this class and initialize auth """ global aliases, server_version, protocol_version, verbosity aliases = Aliases server_version = ServerVersion protocol_version = ProtocolVersion verbosity = Verbosity + + auth.init(Password) + + def authenticate(): + pass # builds an header def header(CodeList, AdditionalHeaderLines = ""): @@ -39,10 +46,10 @@ class comm: for i in range(0, len(CodeList)): ret += CodeList[int(i)] + " " +\ statuscodes.description['s' + CodeList[int(i)]] + "\n" - ret += "ServerVersion: " + server_version + "\n" +\ - AdditionalHeaderLines + "\n\n" + ret += AdditionalHeaderLines + "\n\n" return ret + # formats a massage def encode_message(text): """ @@ -50,6 +57,7 @@ class comm: """ return text.replace('{', '\{').replace('}', '\}') + # "deformats" a message def decode_message(text): """ @@ -57,12 +65,14 @@ class comm: """ return text.replace('\{', '{').replace('\}', '}') + # returns the motd def motd(motd): """ builds and returns a motd package """ - return comm.header(['202', '003']) + comm.encode_message(motd) + return comm.header(['202', '003']) + comm.encode_message(motd) + "\n{END}" + # handles the content def command(client_address, data): @@ -80,12 +90,18 @@ class comm: if verbosity >= 2: print("Got valid service command from" + str(client_address) + ": ", data) - ret = ret +\ - "202 Valid Service Command\n"\ - "002 Version\n"\ - "ServerVersion:" + server_version + "\n"\ + hdr = comm.header(['202','002']) + ret = "ServerVersion:" + server_version + "\n"\ "ProtocolVersion:" + protocol_version + "\n" + # if it's 'exit', then send .. nothing! + elif data == 'exit': + if verbosity >= 2: print("Got valid service command from" + + str(client_address) + ": ", data) + + hdr = comm.header(['202','004']) + ret = "closing connection..." + # if it's 'help', give a little help elif data == 'help': @@ -93,10 +109,10 @@ class comm: + str(client_address) + ": ", data) # send status code - ret = ret + "202 Valid Service Command\n\n" + hdr = comm.header(['202']) # send the list of aliases - ret = ret + "Aviable aliases:\n" + ret = "Aviable aliases:\n" for i in aliases.keys(): ret = ret + str(i) + "\n" @@ -104,9 +120,9 @@ class comm: elif data in aliases: # send status code - ret = ret + "201 Valid Command\n\n" + hdr = comm.header(['201']) - # ohmagawd! a debug message!!1! + # ohmagawd! a debug message!!1! (sry...) if verbosity >= 2: print("Got valid command from" + str(client_address) + ": ", data) @@ -125,11 +141,11 @@ class comm: else: # send status code - ret = ret + "203 Invalid Command\n" + hdr = comm.header(['203']) if verbosity >= 2: print("Got invalid command from", str(client_address), ": ", data) - ret = ret + "{END}\n" + ret = comm.encode_message(ret) + "{END}\n\n" - return ret \ No newline at end of file + return hdr + ret diff --git a/include/statuscodes.py b/include/statuscodes.py index 378ceb9..d3a9ad8 100644 --- a/include/statuscodes.py +++ b/include/statuscodes.py @@ -1,7 +1,7 @@ # include/statuscodes.py # -# module version: 1.0.20130426 -# for protocol versions 0.2.20130423 and later +# module version: 1.0.20130617 +# for protocol version 0.2.20130617 # @@ -12,6 +12,7 @@ class statuscodes: s001 = "OK", s002 = "Version", s003 = "MOTD", + s004 = "Exit", # 100 authentication and maintenance s101 = "Challenge", s102 = "Success",