Exemple #1
0
    def restore(self):
        """
        restore the encrypted config and token data from a backup file

        the restore relies on a backup file, which was created by
        the migrate/backup command. The file contains per line a config or
        token entry, where each line is a json dump. The first line of the
        backup file contains the salt, the last one the number of entries
        written

        :param pass: passphrase used for encrypting data in the backup file
        :param backupid: used to controll the intermediate backup file

        """
        params = {}
        backup_file = ""
        remove_backup_file = True
        try:
            params.update(request.params)

            try:
                backupid = params['backupid']
                passphrase = params['pass']
                remove_backup_file = (
                            params.get("remove_backup", "True") == "True")
            except KeyError as exx:
                raise Exception("missing Parameter:%r" % exx)

            mig = None

            # get the backup file
            backup_file = hashlib.sha256(backupid).digest()[:16]
            backup_file = "%s.hbak" % binascii.hexlify(backup_file)

            if not os.path.isfile(backup_file):
                raise Exception("No restore file found for backupid=%s"
                                % backupid)

            counters = {}
            counter_check_done = False
            with open(backup_file, 'r') as f:
                for data in f.readlines():

                    if not data.strip():  # skip empty lines
                        continue

                    restore_data = json.loads(data)

                    if not mig and  "Salt" in restore_data:
                        salt = restore_data["Salt"]
                        mig = MigrationHandler()
                        mig.setup(passphrase=passphrase,
                                  salt=binascii.unhexlify(salt))

                    elif "Config" in restore_data and mig:
                        config_entry = restore_data['Config']
                        mig.set_config_entry(config_entry)
                        counters["Config"] = counters.get("Config", 0) + 1

                    elif "Token" in restore_data and mig:
                        token_entry = restore_data['Token']
                        mig.set_token_data(token_entry)
                        counters["Token"] = counters.get("Token", 0) + 1

                    # Counters is the last entry - compare the counters
                    elif "Counter" in restore_data and mig:

                        # check inzegryty for 'number of entries'
                        backup_data = restore_data["Counter"]

                        mac = mig.calculate_mac(json.dumps(backup_data))
                        if binascii.hexlify(mac) != restore_data["mac"]:
                            raise Exception("Restore Lines mismatch")

                        if (restore_data["Counter"].get("Token") !=
                                counters.get("Token", 0)):
                            raise Exception("Restore Token mismatch")

                        if (restore_data["Counter"].get("Config") !=
                                counters.get("Config", 0)):
                            raise Exception("Restore Config mismatch")

                        counter_check_done = True

                    else:
                        if not mig:
                            raise Exception('MigrationHandler not initialized!')
                        else:
                            log.info("unknown entry")

            # if somebody removed the last line, we cry for it
            if not counter_check_done:
                raise Exception('incomplete migration file!')

            return sendResult(response, counters)

        except PolicyException as pe:
            log.exception('[show] policy failed: %r' % pe)
            return sendError(response, unicode(pe), 1)

        except Exception as e:
            log.exception('[show] failed: %r' % e)
            Session.rollback()
            return sendError(response, e)

        finally:
            if remove_backup_file and os.path.isfile(backup_file):
                os.remove(backup_file)
            Session.close()
            log.debug("[restore] done")
Exemple #2
0
    def backup(self):
        """
        create a backup of
        - the encrypted token data, which could be
            seed or pin (if encrypted) or userpin (used in motp, ocra2)
        - the config entries of type password

        the data
            - is encrypte with a given passphrase
            - and stored in an backup file (defined by the hash of backupid)

        :param pass: passphrase used for encrypting data in the backup file
        :param backupid: used to controll the intermediate backup file

        """

        try:
            try:
                backupid = self.request_params['backupid']
                passphrase = self.request_params['pass']
            except KeyError as exx:
                raise Exception("missing Parameter:%r" % exx)

            backup_data = {}

            mig = MigrationHandler()
            salt = mig.setup(passphrase=passphrase)

            # create the backup file
            b_name = hashlib.sha256(backupid).digest()[:16]
            b_name = "%s.hbak" % binascii.hexlify(b_name)

            with open(b_name, 'w') as f:
                f.write(json.dumps({'Salt': binascii.hexlify(salt)}))
                f.write("\n")

                i = 0
                for data in mig.get_config_items():
                    f.write(json.dumps({"Config": data}))
                    f.write("\n")
                    i += 1
                backup_data["Config"] = i

                i = 0
                for data in mig.get_token_data():
                    f.write(json.dumps({"Token": data}))
                    f.write("\n")
                    i += 1
                backup_data["Token"] = i

                mac = mig.calculate_mac(json.dumps(backup_data))
                f.write(
                    json.dumps({
                        "Counter": backup_data,
                        'mac': binascii.hexlify(mac)
                    }))
                f.write("\n")

            result = {}
            for val in ['Token', 'Config']:
                result[val] = backup_data[val]

            return sendResult(response, result)

        except PolicyException as pe:
            db.session.rollback()
            log.exception('[backup] policy failed: %r' % pe)
            return sendError(response, str(pe), 1)

        except Exception as e:
            db.session.rollback()
            log.exception('[backup] failed: %r' % e)
            return sendError(response, e)
Exemple #3
0
    def backup(self):
        """
        create a backup of
        - the encrypted token data, which could be
            seed or pin (if encrypted) or userpin (used in motp, ocra)
        - the config entries of type password

        the data
            - is encrypte with a given passphrase
            - and stored in an backup file (defined by the hash of backupid)

        :param pass: passphrase used for encrypting data in the backup file
        :param backupid: used to controll the intermediate backup file

        """
        params = {}
        try:
            params.update(request.params)

            try:
                backupid = params['backupid']
                passphrase = params['pass']
            except KeyError as exx:
                raise Exception("missing Parameter:%r" % exx)

            backup_data = {}

            mig = MigrationHandler()
            salt = mig.setup(passphrase=passphrase)

            # create the backup file
            b_name = hashlib.sha256(backupid).digest()[:16]
            b_name = "%s.hbak" % binascii.hexlify(b_name)

            with open(b_name, 'w') as f:
                f.write(json.dumps({'Salt': binascii.hexlify(salt)}))
                f.write("\n")

                i = 0
                for data in mig.get_config_items():
                    f.write(json.dumps({"Config": data}))
                    f.write("\n")
                    i += 1
                backup_data["Config"] = i

                i = 0
                for data in mig.get_token_data():
                    f.write(json.dumps({"Token": data}))
                    f.write("\n")
                    i += 1
                backup_data["Token"] = i

                mac = mig.calculate_mac(json.dumps(backup_data))
                f.write(json.dumps({"Counter": backup_data,
                                    'mac': binascii.hexlify(mac)}))
                f.write("\n")

            result = {}
            for val in ['Token', 'Config']:
                result[val] = backup_data[val]

            return sendResult(response, result)

        except PolicyException as pe:
            log.exception('[show] policy failed: %r' % pe)
            return sendError(response, unicode(pe), 1)

        except Exception as e:
            log.exception('[show] failed: %r' % e)
            return sendError(response, e)

        finally:
            log.debug("[show] done")
Exemple #4
0
    def restore(self):
        """
        restore the encrypted config and token data from a backup file

        the restore relies on a backup file, which was created by
        the migrate/backup command. The file contains per line a config or
        token entry, where each line is a json dump. The first line of the
        backup file contains the salt, the last one the number of entries
        written

        :param pass: passphrase used for encrypting data in the backup file
        :param backupid: used to controll the intermediate backup file
        :param remove_backup (optional): if set to False, backup file will not
                be deleted after backup.
                Default is that backup is deleted, even in case of error

        """
        backup_file = ""
        remove_backup_file = True

        # error conditions
        missing_param = False
        decryption_error = False

        try:
            try:
                backupid = self.request_params['backupid']
                passphrase = self.request_params['pass']
                remove_backup_file = (self.request_params.get(
                    "remove_backup", "true").lower() == "true")
            except KeyError as exx:
                missing_param = True
                raise Exception("missing Parameter:%r" % exx)

            mig = None

            # get the backup file
            backup_file = hashlib.sha256(backupid).digest()[:16]
            backup_file = "%s.hbak" % binascii.hexlify(backup_file)

            if not os.path.isfile(backup_file):
                raise Exception("No restore file found for backupid=%s" %
                                backupid)

            counters = {}
            counter_check_done = False
            with open(backup_file, 'r') as f:
                for data in f.readlines():

                    if not data.strip():  # skip empty lines
                        continue

                    restore_data = json.loads(data)

                    if not mig and "Salt" in restore_data:
                        salt = restore_data["Salt"]
                        mig = MigrationHandler()
                        mig.setup(passphrase=passphrase,
                                  salt=binascii.unhexlify(salt))

                    elif "Config" in restore_data and mig:
                        config_entry = restore_data['Config']
                        mig.set_config_entry(config_entry)
                        counters["Config"] = counters.get("Config", 0) + 1

                    elif "Token" in restore_data and mig:
                        token_entry = restore_data['Token']
                        mig.set_token_data(token_entry)
                        counters["Token"] = counters.get("Token", 0) + 1

                    # Counters is the last entry - compare the counters
                    elif "Counter" in restore_data and mig:

                        # check inzegryty for 'number of entries'
                        backup_data = restore_data["Counter"]

                        mac = mig.calculate_mac(json.dumps(backup_data))
                        if binascii.hexlify(mac) != restore_data["mac"]:
                            raise Exception("Restore Lines mismatch")

                        if (restore_data["Counter"].get("Token") !=
                                counters.get("Token", 0)):
                            raise Exception("Restore Token mismatch")

                        if (restore_data["Counter"].get("Config") !=
                                counters.get("Config", 0)):
                            raise Exception("Restore Config mismatch")

                        counter_check_done = True

                    else:
                        if not mig:
                            raise Exception('MigrationHandler not '
                                            'initialized!')
                        else:
                            log.info("unknown entry")

            # if somebody removed the last line, we cry for it
            if not counter_check_done:
                raise Exception('incomplete migration file!')

            db.session.commit()
            log.debug("[restore] success")
            return sendResult(response, counters)

        except PolicyException as pe:
            log.exception('[restore] policy failed: %r' % pe)
            return sendError(response, str(pe), 1)

        except DecryptionError as err:
            decryption_error = True
            log.exception('Error - failed with %r' % err)
            db.session.rollback()
            return sendError(response, err)

        except Exception as err:
            log.exception('Error - failed with %r' % err)
            db.session.rollback()
            return sendError(response, err)

        finally:

            if remove_backup_file and os.path.isfile(backup_file):
                if not missing_param and not decryption_error:
                    os.remove(backup_file)
                    log.debug("removed backup file %r", backup_file)