=== modified file 'TODO' --- TODO 2011-11-09 17:16:03 +0000 +++ TODO 2011-11-10 11:08:50 +0000 @@ -41,6 +41,7 @@ * mandos (server) ** TODO [#B] Log level :BUGS: +** TODO [#A] Move approval to Client from ClientDBus *** TODO /etc/mandos/clients.d/*.conf Watch this directory and add/remove/update clients? === modified file 'debian/control' --- debian/control 2011-10-11 19:36:00 +0000 +++ debian/control 2011-11-10 11:08:50 +0000 @@ -17,7 +17,7 @@ Architecture: all Depends: ${misc:Depends}, python (>=2.6), python-gnutls, python-dbus, python-avahi, python-gobject, avahi-daemon, adduser, - python-urwid, python (>=2.7) | python-argparse + python-urwid, python (>=2.7) | python-argparse, python-crypto Recommends: fping Description: server giving encrypted passwords to Mandos clients This is the server part of the Mandos system, which allows === modified file 'mandos' --- mandos 2011-11-09 17:16:03 +0000 +++ mandos 2011-11-10 11:08:50 +0000 @@ -310,9 +310,9 @@ interval: datetime.timedelta(); How often to start a new checker last_approval_request: datetime.datetime(); (UTC) or None last_checked_ok: datetime.datetime(); (UTC) or None - last_checker_status: integer between 0 and 255 reflecting exit status - of last checker. -1 reflect crashed checker, - or None. + last_checker_status: integer between 0 and 255 reflecting exit + status of last checker. -1 reflect crashed + checker, or None. last_enabled: datetime.datetime(); (UTC) name: string; from the config file, used in log messages and D-Bus identifiers @@ -398,12 +398,16 @@ self.changedstate = (multiprocessing_manager .Condition(multiprocessing_manager .Lock())) - self.client_structure = [attr for attr in self.__dict__.iterkeys() if not attr.startswith("_")] + self.client_structure = [attr for attr + in self.__dict__.iterkeys() + if not attr.startswith("_")] self.client_structure.append("client_structure") for name, t in inspect.getmembers(type(self), - lambda obj: isinstance(obj, property)): + lambda obj: + isinstance(obj, + property)): if not name.startswith("_"): self.client_structure.append(name) @@ -591,14 +595,17 @@ raise self.checker = None - # Encrypts a client secret and stores it in a varible encrypted_secret + # Encrypts a client secret and stores it in a varible + # encrypted_secret def encrypt_secret(self, key): - # Encryption-key need to be of a specific size, so we hash inputed key + # Encryption-key need to be of a specific size, so we hash + # supplied key hasheng = hashlib.sha256() hasheng.update(key) encryptionkey = hasheng.digest() - # Create validation hash so we know at decryption if it was sucessful + # Create validation hash so we know at decryption if it was + # sucessful hasheng = hashlib.sha256() hasheng.update(self.secret) validationhash = hasheng.digest() @@ -612,7 +619,8 @@ # Decrypt a encrypted client secret def decrypt_secret(self, key): - # Decryption-key need to be of a specific size, so we hash inputed key + # Decryption-key need to be of a specific size, so we hash + # supplied key hasheng = hashlib.sha256() hasheng.update(key) encryptionkey = hasheng.digest() @@ -629,8 +637,8 @@ secret = plain[hasheng.digest_size:] hasheng.update(secret) - # if validation fails, we use key as new secret. Otherwhise, we use - # the decrypted secret + # If validation fails, we use key as new secret. Otherwise, we + # use the decrypted secret if hasheng.digest() == validationhash: self.secret = secret else: @@ -944,9 +952,11 @@ def __init__(self, bus = None, *args, **kwargs): self.bus = bus + self._approvals_pending = 0 Client.__init__(self, *args, **kwargs) - - self._approvals_pending = 0 + self.add_to_dbus() + + def add_to_dbus(self): # Only now, when this client is initialized, can it show up on # the D-Bus client_object_name = unicode(self.name).translate( @@ -1922,7 +1932,8 @@ parser.add_argument("--no-ipv6", action="store_false", dest="use_ipv6", help="Do not use IPv6") parser.add_argument("--no-restore", action="store_false", - dest="restore", help="Do not restore stored state", + dest="restore", + help="Do not restore stored state", default=True) options = parser.parse_args() @@ -2125,9 +2136,12 @@ # with exceptions for any special settings as defined above client_settings = dict((clientname, dict((setting, - (value if setting not in special_settings - else special_settings[setting](clientname))) - for setting, value in client_config.items(clientname))) + (value if + setting not in special_settings + else special_settings[setting] + (clientname))) + for setting, value + in client_config.items(clientname))) for clientname in client_config.sections()) old_client_settings = {} @@ -2137,10 +2151,12 @@ if server_settings["restore"]: try: with open(stored_state_path, "rb") as stored_state: - clients_data, old_client_settings = pickle.load(stored_state) + clients_data, old_client_settings = ( + pickle.load(stored_state)) os.remove(stored_state_path) except IOError as e: - logger.warning("Could not load persistant state: {0}".format(e)) + logger.warning("Could not load persistant state: {0}" + .format(e)) if e.errno != errno.ENOENT: raise @@ -2157,39 +2173,37 @@ # For each value in new config, check if it differs # from the old config value (Except for the "secret" # attribute) - if name != "secret" and value != old_client_settings[client_name][name]: + if (name != "secret" and + value != old_client_settings[client_name][name]): setattr(client, name, value) except KeyError: pass - # Clients who has passed its expire date, can still be enabled if its - # last checker was sucessful. Clients who checkers failed before we - # stored it state is asumed to had failed checker during downtime. + # Clients who has passed its expire date, can still be enabled + # if its last checker was sucessful. Clients who checkers + # failed before we stored it state is asumed to had failed + # checker during downtime. if client["enabled"] and client["last_checked_ok"]: - if ((datetime.datetime.utcnow() - client["last_checked_ok"]) - > client["interval"]): + if ((datetime.datetime.utcnow() + - client["last_checked_ok"]) > client["interval"]): if client["last_checker_status"] != 0: client["enabled"] = False else: - client["expires"] = datetime.datetime.utcnow() + client["timeout"] + client["expires"] = (datetime.datetime.utcnow() + + client["timeout"]) client["changedstate"] = (multiprocessing_manager .Condition(multiprocessing_manager .Lock())) if use_dbus: - new_client = ClientDBusTransitional.__new__(ClientDBusTransitional) + new_client = ClientDBusTransitional.__new__( + ClientDBusTransitional) tcp_server.clients[client_name] = new_client new_client.bus = bus for name, value in client.iteritems(): setattr(new_client, name, value) - client_object_name = unicode(client_name).translate( - {ord("."): ord("_"), - ord("-"): ord("_")}) - new_client.dbus_object_path = (dbus.ObjectPath - ("/clients/" + client_object_name)) - DBusObjectWithProperties.__init__(new_client, - new_client.bus, - new_client.dbus_object_path) + new_client._approvals_pending = 0 + new_client.add_to_dbus() else: tcp_server.clients[client_name] = Client.__new__(Client) for name, value in client.iteritems(): @@ -2202,12 +2216,12 @@ for clientname in set(old_client_settings) - set(client_settings): del tcp_server.clients[clientname] for clientname in set(client_settings) - set(old_client_settings): - tcp_server.clients[clientname] = (client_class(name = clientname, - config = - client_settings - [clientname])) + tcp_server.clients[clientname] = client_class(name + = clientname, + config = + client_settings + [clientname]) - if not tcp_server.clients: logger.warning("No clients defined") @@ -2296,17 +2310,19 @@ if not (tcp_server.clients or client_settings): return - # Store client before exiting. Secrets are encrypted with key based - # on what config file has. If config file is removed/edited, old - # secret will thus be unrecovable. + # Store client before exiting. Secrets are encrypted with key + # based on what config file has. If config file is + # removed/edited, old secret will thus be unrecovable. clients = [] for client in tcp_server.clients.itervalues(): - client.encrypt_secret(client_settings[client.name]["secret"]) + client.encrypt_secret( + client_settings[client.name]["secret"]) client_dict = {} - # A list of attributes that will not be stored when shuting down. - exclude = set(("bus", "changedstate", "secret")) + # A list of attributes that will not be stored when + # shutting down. + exclude = set(("bus", "changedstate", "secret")) for name, typ in inspect.getmembers(dbus.service.Object): exclude.add(name) @@ -2319,10 +2335,14 @@ del client_settings[client.name]["secret"] try: - with os.fdopen(os.open(stored_state_path, os.O_CREAT|os.O_WRONLY|os.O_TRUNC, 0600), "wb") as stored_state: + with os.fdopen(os.open(stored_state_path, + os.O_CREAT|os.O_WRONLY|os.O_TRUNC, + stat.S_IRUSR | stat.S_IWUSR), + "wb") as stored_state: pickle.dump((clients, client_settings), stored_state) except IOError as e: - logger.warning("Could not save persistant state: {0}".format(e)) + logger.warning("Could not save persistant state: {0}" + .format(e)) if e.errno != errno.ENOENT: raise