| """RPC Server module.""" | 
 |  | 
 | import sys | 
 | import socket | 
 | import pickle | 
 | from fnmatch import fnmatch | 
 | from reprlib import repr | 
 |  | 
 |  | 
 | # Default verbosity (0 = silent, 1 = print connections, 2 = print requests too) | 
 | VERBOSE = 1 | 
 |  | 
 |  | 
 | class Server: | 
 |  | 
 |     """RPC Server class.  Derive a class to implement a particular service.""" | 
 |  | 
 |     def __init__(self, address, verbose = VERBOSE): | 
 |         if type(address) == type(0): | 
 |             address = ('', address) | 
 |         self._address = address | 
 |         self._verbose = verbose | 
 |         self._socket = None | 
 |         self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | 
 |         self._socket.bind(address) | 
 |         self._socket.listen(1) | 
 |         self._listening = 1 | 
 |  | 
 |     def _setverbose(self, verbose): | 
 |         self._verbose = verbose | 
 |  | 
 |     def __del__(self): | 
 |         self._close() | 
 |  | 
 |     def _close(self): | 
 |         self._listening = 0 | 
 |         if self._socket: | 
 |             self._socket.close() | 
 |         self._socket = None | 
 |  | 
 |     def _serverloop(self): | 
 |         while self._listening: | 
 |             self._serve() | 
 |  | 
 |     def _serve(self): | 
 |         if self._verbose: print("Wait for connection ...") | 
 |         conn, address = self._socket.accept() | 
 |         if self._verbose: print("Accepted connection from %s" % repr(address)) | 
 |         if not self._verify(conn, address): | 
 |             print("*** Connection from %s refused" % repr(address)) | 
 |             conn.close() | 
 |             return | 
 |         rf = conn.makefile('r') | 
 |         wf = conn.makefile('w') | 
 |         ok = 1 | 
 |         while ok: | 
 |             wf.flush() | 
 |             if self._verbose > 1: print("Wait for next request ...") | 
 |             ok = self._dorequest(rf, wf) | 
 |  | 
 |     _valid = ['192.16.201.*', '192.16.197.*', '132.151.1.*', '129.6.64.*'] | 
 |  | 
 |     def _verify(self, conn, address): | 
 |         host, port = address | 
 |         for pat in self._valid: | 
 |             if fnmatch(host, pat): return 1 | 
 |         return 0 | 
 |  | 
 |     def _dorequest(self, rf, wf): | 
 |         rp = pickle.Unpickler(rf) | 
 |         try: | 
 |             request = rp.load() | 
 |         except EOFError: | 
 |             return 0 | 
 |         if self._verbose > 1: print("Got request: %s" % repr(request)) | 
 |         try: | 
 |             methodname, args, id = request | 
 |             if '.' in methodname: | 
 |                 reply = (None, self._special(methodname, args), id) | 
 |             elif methodname[0] == '_': | 
 |                 raise NameError("illegal method name %s" % repr(methodname)) | 
 |             else: | 
 |                 method = getattr(self, methodname) | 
 |                 reply = (None, method(*args), id) | 
 |         except: | 
 |             reply = (sys.exc_info()[:2], id) | 
 |         if id < 0 and reply[:2] == (None, None): | 
 |             if self._verbose > 1: print("Suppress reply") | 
 |             return 1 | 
 |         if self._verbose > 1: print("Send reply: %s" % repr(reply)) | 
 |         wp = pickle.Pickler(wf) | 
 |         wp.dump(reply) | 
 |         return 1 | 
 |  | 
 |     def _special(self, methodname, args): | 
 |         if methodname == '.methods': | 
 |             if not hasattr(self, '_methods'): | 
 |                 self._methods = tuple(self._listmethods()) | 
 |             return self._methods | 
 |         raise NameError("unrecognized special method name %s" % repr(methodname)) | 
 |  | 
 |     def _listmethods(self, cl=None): | 
 |         if not cl: cl = self.__class__ | 
 |         names = sorted([x for x in cl.__dict__.keys() if x[0] != '_']) | 
 |         for base in cl.__bases__: | 
 |             basenames = self._listmethods(base) | 
 |             basenames = list(filter(lambda x, names=names: x not in names, basenames)) | 
 |             names[len(names):] = basenames | 
 |         return names | 
 |  | 
 |  | 
 | from security import Security | 
 |  | 
 |  | 
 | class SecureServer(Server, Security): | 
 |  | 
 |     def __init__(self, *args): | 
 |         Server.__init__(self, *args) | 
 |         Security.__init__(self) | 
 |  | 
 |     def _verify(self, conn, address): | 
 |         import string | 
 |         challenge = self._generate_challenge() | 
 |         conn.send("%d\n" % challenge) | 
 |         response = "" | 
 |         while "\n" not in response and len(response) < 100: | 
 |             data = conn.recv(100) | 
 |             if not data: | 
 |                 break | 
 |             response = response + data | 
 |         try: | 
 |             response = string.atol(string.strip(response)) | 
 |         except string.atol_error: | 
 |             if self._verbose > 0: | 
 |                 print("Invalid response syntax", repr(response)) | 
 |             return 0 | 
 |         if not self._compare_challenge_response(challenge, response): | 
 |             if self._verbose > 0: | 
 |                 print("Invalid response value", repr(response)) | 
 |             return 0 | 
 |         if self._verbose > 1: | 
 |             print("Response matches challenge.  Go ahead!") | 
 |         return 1 |