Search code examples
pythonauthenticationtwistedxml-rpcchallenge-response

How to add authentication to a (Python) twisted xmlrpc server


I am trying to add authentication to a xmlrpc server (which will be running on nodes of a P2P network) without using user:password@host as this will reveal the password to all attackers. The authentication is so to basically create a private network, preventing unauthorised users from accessing it.

My solution to this was to create a challenge response system very similar to this but I have no clue how to add this to the xmlrpc server code. I found a similar question (Where custom authentication was needed) here.

So I tried creating a module that would be called whenever a client connected to the server. This would connect to a challenge-response server running on the client and if the client responded correctly would return True. The only problem was that I could only call the module once and then I got a reactor cannot be restarted error. So is there some way of having a class that whenever the "check()" function is called it will connect and do this?

Would the simplest thing to do be to connect using SSL? Would that protect the password? Although this solution would not be optimal as I am trying to avoid having to generate SSL certificates for all the nodes.


Solution

  • For anyone that was looking for a full example below is mine (thanks to Rakis for pointing me in the right direction). In this the user and password is stored in a file called 'passwd' (see the first useful link for more details and how to change it).

    Server:

    #!/usr/bin/env python
    import bjsonrpc
    from SRPSocket import SRPSocket
    import SocketServer
    from bjsonrpc.handlers import BaseHandler
    import time
    
    class handler(BaseHandler):
        def time(self):
            return time.time()
    
    class SecureServer(SRPSocket.SRPHost):
        def auth_socket(self, socket):
            server = bjsonrpc.server.Server(socket, handler_factory=handler)
            server.serve()
    
    s = SocketServer.ForkingTCPServer(('', 1337), SecureServer)
    s.serve_forever()
    

    Client:

    #! /usr/bin/env python
    import bjsonrpc
    from bjsonrpc.handlers import BaseHandler
    from SRPSocket import SRPSocket
    import time
    
    class handler(BaseHandler):
        def time(self):
            return time.time()
    
    socket, key = SRPSocket.SRPSocket('localhost', 1337, 'dht', 'testpass')
    
    connection = bjsonrpc.connection.Connection(socket, handler_factory=handler)
    
    test = connection.call.time()
    print test
    time.sleep(1)
    

    Some useful links: