def testSmallFile(self): clear_file = tempfile.NamedTemporaryFile(delete=False, dir=self.testdir) crypt_file = tempfile.NamedTemporaryFile(delete=False, dir=self.testdir) clear_file2 = tempfile.NamedTemporaryFile(delete=False, dir=self.testdir) clear_file.write("abc") clear_file.close() crypt_file.close() clear_file2.close() encrypt_file(self.password, clear_file.name, crypt_file.name) decrypt_file(self.password, crypt_file.name, clear_file2.name) self.assertTrue(filecmp.cmp(clear_file.name, clear_file2.name, shallow=False)) self.assertFalse(filecmp.cmp(clear_file.name, crypt_file.name, shallow=False))
def testOpenSSLCompatabilityDecrypt(self): clear_file = tempfile.NamedTemporaryFile(delete=False, dir=self.testdir) crypt_file = tempfile.NamedTemporaryFile(delete=False, dir=self.testdir) clear_file2 = tempfile.NamedTemporaryFile(delete=False, dir=self.testdir) clear_file.write(self.tinydata) clear_file.close() crypt_file.close() clear_file2.close() cmd = "openssl enc -md sha256 -aes-256-cbc -pass pass:%s -in %s -out %s" % \ (self.password, clear_file.name, crypt_file.name) os.system(cmd) decrypt_file(self.password, crypt_file.name, clear_file2.name) self.assertTrue(filecmp.cmp(clear_file.name, clear_file2.name, shallow=False)) self.assertFalse(filecmp.cmp(clear_file.name, crypt_file.name, shallow=False))
def onShowPackages(self, event): # Fetch the package list from the last run of the selected backup if self.cboBackup.Count == 0: return # Get the backup and store bname = self.cboBackup.GetStringSelection() backup = self.config.backups[bname] store = self.config.storage[backup.store].copy() # Figure out the last run runs = self.db.runs(bname) if len(runs) == 0: dlg.Info(self, _("The selected backup has not run")) return # last is the most recent run = runs[-1] # Get the folder folder = os.path.join(bname, run.start_time_str + ' ' + run.type) src = os.path.join(folder, const.PackageFile) if backup.encrypt: src = src + const.EncryptionSuffix workfolder = tempfile.mkdtemp() store.connect() store.copy_from(src, workfolder) store.disconnect() package_path = os.path.join(workfolder, const.PackageFile) if backup.encrypt: crypt_path = package_path + const.EncryptionSuffix cryptor.decrypt_file(self.config.data_passphrase, crypt_path, package_path) package_list = open(package_path).read().split('\n') # Cleanup shutil.rmtree(workfolder) win = PackageWindow(self, package_list)
def recover_run(config, db, backup, store, run): wx.Yield() # Grab the LOF tmp_dir = tempfile.mkdtemp() try: # Create encrypted and clear pathnames lof_remote = os.path.join(backup.name, run, const.LOFFile) lof_remote_enc = os.path.join(backup.name, run, const.LOFFile + const.EncryptionSuffix) # Look at the remote site - is it encrypted or not? if store.exists(lof_remote): src = lof_remote encrypted = False elif store.exists(lof_remote_enc): src = lof_remote_enc encrypted = True else: raise Exception(_("Backup '{backup}' run '{run}' is corrupt").format(backup=backup.name, run=run)) # Get the LOF file store.copy_from(src, tmp_dir) lof_file = os.path.join(tmp_dir, const.LOFFile) # Decrypt if required. if encrypted: decrypt_file(config.data_passphrase, lof_file + const.EncryptionSuffix, lof_file) # Now we open and walk through the ZIP file. lof = gzip.GzipFile(lof_file, "rb") folder = "" nfiles = 0 # the config file nfolders = 0 file_sizes = 0 while True: # Get the next line, and remove the CR line = lof.readline() if line is None or line == "": break if line[-1:] == '\n': line = line[:-1] log.debug("Next Line", line) if line == "": # New folder on the next line line = lof.readline() if line is None or line == "": break if line[-1:] == '\n': line = line[:-1] folder = utils.unescape(line) nfolders += 1 else: parts = line.split(",") type = parts[0] name = utils.unescape(parts[1]) path = os.path.join(folder, name) path = utils.path_to_unicode(path) if type == "F" or type == "D": mod_time = parts[2] size = parts[3] db.fs_saved(path, mod_time, size, type) if type == 'F': nfiles += 1 file_sizes += int(size) elif type == 'X': db.fs_deleted(path) else: raise Exception(_("Corrupt type in file list")) wx.Yield() # To calculate the amount of size, we need to see how big the data files are. run_dir = os.path.join(backup.name, run) size = 0 log.debug("Checking files sizes") files = store.list(run_dir) for file in files: size += store.size(os.path.join(run_dir, file)) wx.Yield() finally: shutil.rmtree(tmp_dir) log.trace("Completed recover run: ", size, file_sizes, nfiles, nfolders) return size, file_sizes, nfiles, nfolders
def wiz_execute(wiz): # Connect if wiz.fields["storagetype"].value == _("Local Folder"): store = FolderStore("store", 0, False, wiz.fields["folderpath"].value) elif wiz.fields["storagetype"].value == _("FTP Server"): server = wiz.fields["ftpserver"].value login = wiz.fields["ftplogin"].value password = wiz.fields["ftppassword"].value root = wiz.fields["ftproot"].value sftp = wiz.fields["sftp"].value store = FTPStore("store", 0, False, server, root, login, password, sftp) elif wiz.fields["storagetype"].value == _("DropBox"): login = wiz.fields["dblogin"].value password = wiz.fields["dbpassword"].value root = wiz.fields["dbroot"].value store = DropBoxStore("store", 0, False, root, login, password) elif wiz.fields["storagetype"].value == _("Server Share"): mountcmd = wiz.fields["mountcmd"].value umountcmd = wiz.fields["umountcmd"].value shareroot = wiz.fields["shareroot"].value store = ShareStore("store", 0, False, shareroot, mountcmd, umountcmd) else: raise Exception("Internal error: bad store type") log.debug("Store = ", store) # In case we need to revert our config later orig_config = Config.get_config() try: store.connect() folders = [] # List all backups backups = store.list(".") for backup in backups: # Make sure its not a system folder if backup[0] != "_": try: runs = store.list(backup + "/") for run in runs: folders.append((backup, run)) except: pass log.debug("Folders", folders) if len(folders) == 0: raise Exception(_("There are no backup runs in this store")) # Sort them based on the path name folders.sort(key=lambda item: item[1], reverse=True) # Now the first item is the one to use (as it is the most recent). backupname, backuprun = folders[0] config = os.path.join(backupname, backuprun, const.ConfigName) configenc = config + const.EncryptionSuffix # Check if the config exists. if store.exists(config): src = config encrypted = False elif store.exists(configenc): src = configenc encrypted = True else: raise Exception(_("The backup runs are missing or corrupt (no config files)")) if not encrypted: store.get(src, const.ConfigDir+os.sep) else: # Fetch the file. enc_file = const.ConfigFile + const.EncryptionSuffix clear_file = const.ConfigFile store.get(src, const.ConfigDir+os.sep) # ENCRYPTED bad = True # keep going until we get a good password while bad: password = GetPassword(wiz, backupname, backuprun) if password == None: # User is quitting return # Lets check the file is good. try: log.debug("Decrypting", enc_file, clear_file, password) ret = cryptor.decrypt_file(password, enc_file, clear_file) log.debug("Return from decrypt", ret) if ret != 0: raise Exception(_("Failed encryption")) bad = False if os.path.exists(enc_file): os.remove(enc_file) # Looks like this password is a good one. except: log.info("Invalid backup password") dlg.Warn(wiz, _("Invalid password. Please enter the correct backup password.")) os.remove(clear_file) # Revert the old config orig_config.save() dlg.Info(wiz, _("Your configuration has been restored.\nClick OK to restart the UI..."), _("Restore")) python = sys.executable log.debug("Starting:", const.UIProgram) subprocess.Popen(const.UIProgram) app.quit() except Exception as e: dlg.Warn(wiz, str(e), _("Configuration restore failed")) finally: store.disconnect()