422
422
self.client_structure = [attr for attr in self.__dict__.iterkeys() if not attr.startswith("_")]
423
423
self.client_structure.append("client_structure")
426
425
for name, t in inspect.getmembers(type(self),
427
426
lambda obj: isinstance(obj, property)):
428
427
if not name.startswith("_"):
480
479
# Also start a new checker *right now*.
481
480
self.start_checker()
484
482
def checker_callback(self, pid, condition, command):
485
483
"""The checker has completed, so take appropriate actions."""
486
484
self.checker_callback_tag = None
611
609
if error.errno != errno.ESRCH: # No such process
613
611
self.checker = None
615
613
# Encrypts a client secret and stores it in a varible encrypted_secret
616
614
def encrypt_secret(self, key):
617
615
# Encryption-key need to be of a specific size, so we hash inputed key
618
616
hasheng = hashlib.sha256()
619
617
hasheng.update(key)
620
618
encryptionkey = hasheng.digest()
622
620
# Create validation hash so we know at decryption if it was sucessful
623
621
hasheng = hashlib.sha256()
624
622
hasheng.update(self.secret)
625
623
validationhash = hasheng.digest()
628
626
iv = os.urandom(Crypto.Cipher.AES.block_size)
629
627
ciphereng = Crypto.Cipher.AES.new(encryptionkey,
630
628
Crypto.Cipher.AES.MODE_CFB, iv)
631
629
ciphertext = ciphereng.encrypt(validationhash+self.secret)
632
630
self.encrypted_secret = (ciphertext, iv)
634
632
# Decrypt a encrypted client secret
635
633
def decrypt_secret(self, key):
636
634
# Decryption-key need to be of a specific size, so we hash inputed key
637
635
hasheng = hashlib.sha256()
638
636
hasheng.update(key)
639
637
encryptionkey = hasheng.digest()
641
639
# Decrypt encrypted secret
642
640
ciphertext, iv = self.encrypted_secret
643
641
ciphereng = Crypto.Cipher.AES.new(encryptionkey,
644
642
Crypto.Cipher.AES.MODE_CFB, iv)
645
643
plain = ciphereng.decrypt(ciphertext)
647
645
# Validate decrypted secret to know if it was succesful
648
646
hasheng = hashlib.sha256()
649
647
validationhash = plain[:hasheng.digest_size]
650
648
secret = plain[hasheng.digest_size:]
651
649
hasheng.update(secret)
653
651
# if validation fails, we use key as new secret. Otherwhise, we use
654
652
# the decrypted secret
655
653
if hasheng.digest() == validationhash:
853
851
return dbus.String(dt.isoformat(),
854
852
variant_level=variant_level)
856
855
class AlternateDBusNamesMetaclass(DBusObjectWithProperties
858
857
"""Applied to an empty subclass of a D-Bus object, this metaclass
950
949
attribute.func_closure)))
951
950
return type.__new__(mcs, name, bases, attr)
953
953
class ClientDBus(Client, DBusObjectWithProperties):
954
954
"""A Client class using D-Bus
966
966
def __init__(self, bus = None, *args, **kwargs):
968
968
Client.__init__(self, *args, **kwargs)
970
970
self._approvals_pending = 0
971
971
# Only now, when this client is initialized, can it show up on
1385
1385
return super(ProxyClient, self).__setattr__(name, value)
1386
1386
self._pipe.send(('setattr', name, value))
1388
1389
class ClientDBusTransitional(ClientDBus):
1389
1390
__metaclass__ = AlternateDBusNamesMetaclass
1391
1393
class ClientHandler(socketserver.BaseRequestHandler, object):
1392
1394
"""A class to handle client connections.
1932
1934
parser.add_argument("--no-restore", action="store_false",
1933
1935
dest="restore", help="Do not restore stored state",
1936
1938
options = parser.parse_args()
1938
1940
if options.check:
2171
2173
setattr(client, name, value)
2172
2174
except KeyError:
2175
2177
# Clients who has passed its expire date, can still be enabled if its
2176
2178
# last checker was sucessful. Clients who checkers failed before we
2177
2179
# stored it state is asumed to had failed checker during downtime.
2305
2307
multiprocessing.active_children()
2306
2308
if not (tcp_server.clients or client_settings):
2309
2311
# Store client before exiting. Secrets are encrypted with key based
2310
2312
# on what config file has. If config file is removed/edited, old
2311
2313
# secret will thus be unrecovable.
2313
2315
for client in tcp_server.clients.itervalues():
2314
2316
client.encrypt_secret(client_settings[client.name]["secret"])
2316
2318
client_dict = {}
2318
2320
# A list of attributes that will not be stored when shuting down.
2319
2321
exclude = set(("bus", "changedstate", "secret"))
2320
2322
for name, typ in inspect.getmembers(dbus.service.Object):
2324
2326
for attr in client.client_structure:
2325
2327
if attr not in exclude:
2326
2328
client_dict[attr] = getattr(client, attr)
2328
2330
clients.append(client_dict)
2329
2331
del client_settings[client.name]["secret"]
2335
2337
logger.warning("Could not save persistant state: {0}".format(e))
2336
2338
if e.errno != errno.ENOENT:
2339
2341
# Delete all clients, and settings from config
2340
2342
while tcp_server.clients:
2341
2343
name, client = tcp_server.clients.popitem()