From 7928be91340b023324c016d3d912e87ca52f9c04 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 7 Jan 2014 15:43:18 -0500 Subject: bcfg2-crypt: Protect against double-encrypting data --- src/lib/Bcfg2/Server/Encryption.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/lib/Bcfg2/Server/Encryption.py b/src/lib/Bcfg2/Server/Encryption.py index c96e7ad21..f7f636659 100755 --- a/src/lib/Bcfg2/Server/Encryption.py +++ b/src/lib/Bcfg2/Server/Encryption.py @@ -173,6 +173,17 @@ def ssl_encrypt(plaintext, passwd, algorithm=None, salt=None): return b64encode("Salted__" + salt + crypted) + "\n" +def is_encrypted(val): + """ Make a best guess if the value is encrypted or not. This just + checks to see if ``val`` is a base64-encoded string whose content + starts with "Salted__", so it may have (rare) false positives. It + will not have false negatives. """ + try: + return b64decode(val).startswith("Salted__") + except: # pylint: disable=W0702 + return False + + def bruteforce_decrypt(crypted, passphrases=None, algorithm=None): """ Convenience method to decrypt the given encrypted string by trying the given passphrases or all passphrases sequentially until @@ -323,6 +334,8 @@ class CfgEncryptor(Encryptor): Bcfg2.Options.setup.config) def encrypt(self): + if is_encrypted(self.data): + raise EncryptError("Data is alraedy encrypted") return ssl_encrypt(self.data, self.passphrase) def get_destination_filename(self, original_filename): @@ -429,6 +442,9 @@ class PropertiesEncryptor(Encryptor, PropertiesCryptoMixin): def encrypt(self): xdata = lxml.etree.XML(self.data, parser=XMLParser) for elt in self._get_elements(xdata): + if is_encrypted(elt.text): + raise EncryptError("Element is already encrypted: %s" % + print_xml(elt)) try: pname, passphrase = self._get_element_passphrase(elt) except PassphraseError: -- cgit v1.2.3-1-g7c22