def test_dirname(self): """ test if we generated a dirname """ td = tempdir.default() dirname = td.dir() self.assertTrue( dirname is not None ) """ test if duplicity's temp files are created in our temp dir """ f1d, f1_name = tempdir.default().mkstemp() f1_dirname = os.path.dirname( f1_name ) self.assertTrue( dirname == f1_dirname ) """ test if tempfile creates in our temp dir now as well by default """ f2 = tempfile.NamedTemporaryFile() f2_dirname = os.path.dirname( f2.name ) self.assertTrue( dirname == f2_dirname ) # cleanup os.close(f1d) os.unlink(f1_name) td.forget(f1_name) f2.close() td.cleanup()
def test_dirname(self): u""" test if we generated a dirname """ td = tempdir.default() dirname = td.dir() self.assertTrue(dirname is not None) u""" test if duplicity's temp files are created in our temp dir """ f1d, f1_name = tempdir.default().mkstemp() f1_dirname = os.path.dirname(f1_name) self.assertTrue(dirname == f1_dirname) u""" test if tempfile creates in our temp dir now as well by default """ f2 = tempfile.NamedTemporaryFile() f2_dirname = os.path.dirname(f2.name) self.assertTrue(dirname == f2_dirname) # cleanup os.close(f1d) os.unlink(f1_name) td.forget(f1_name) f2.close() td.cleanup()
def delete(self, filename_list): """Delete files.""" delete_list = filename_list dont_delete_list = [] for file in self.list(): if file in delete_list: delete_list.remove(file) else: dont_delete_list.append(file) if len(delete_list) > 0: raise BackendException("Files %s not found" % str(delete_list)) dir = tempfile.mkdtemp() exclude, exclude_name = tempdir.default().mkstemp_file() to_delete = [exclude_name] for file in dont_delete_list: path = os.path.join(dir, file) to_delete.append(path) f = open(path, 'w') print >> exclude, file f.close() exclude.close() commandline = ("%s --recursive --delete --exclude-from=%s %s/ %s" % (self.cmd, exclude_name, dir, self.url_string)) self.run_command(commandline) for file in to_delete: util.ignore_missing(os.unlink, file) os.rmdir(dir)
def __init__(self, parsed_url): duplicity.backend.Backend.__init__(self, parsed_url) # we expect an error return, so go low-level and ignore it try: p = os.popen(u"ncftpls -v") fout = p.read() ret = p.close() except Exception: pass # the expected error is 8 in the high-byte and some output if ret != 0x0800 or not fout: log.FatalError(u"NcFTP not found: Please install NcFTP version 3.1.9 or later", log.ErrorCode.ftp_ncftp_missing) # version is the second word of the first line version = fout.split(u'\n')[0].split()[1] if version < u"3.1.9": log.FatalError(u"NcFTP too old: Duplicity requires NcFTP version 3.1.9," u"3.2.1 or later. Version 3.2.0 will not work properly.", log.ErrorCode.ftp_ncftp_too_old) elif version == u"3.2.0": log.Warn(u"NcFTP (ncftpput) version 3.2.0 may fail with duplicity.\n" u"see: http://www.ncftpd.com/ncftp/doc/changelog.html\n" u"If you have trouble, please upgrade to 3.2.1 or later", log.WarningCode.ftp_ncftp_v320) log.Notice(u"NcFTP version is %s" % version) self.parsed_url = parsed_url self.url_string = duplicity.backend.strip_auth_from_url(self.parsed_url) # strip ncftp+ prefix self.url_string = duplicity.backend.strip_prefix(self.url_string, u'ncftp') # This squelches the "file not found" result from ncftpls when # the ftp backend looks for a collection that does not exist. # version 3.2.2 has error code 5, 1280 is some legacy value self.popen_breaks[u'ncftpls'] = [5, 1280] # Use an explicit directory name. if self.url_string[-1] != u'/': self.url_string += u'/' self.password = self.get_password() if globals.ftp_connection == u'regular': self.conn_opt = u'-E' else: self.conn_opt = u'-F' self.tempfile, self.tempname = tempdir.default().mkstemp() os.write(self.tempfile, u"host %s\n" % self.parsed_url.hostname) os.write(self.tempfile, u"user %s\n" % self.parsed_url.username) os.write(self.tempfile, u"pass %s\n" % self.password) os.close(self.tempfile) self.flags = u"-f %s %s -t %s -o useCLNT=0,useHELP_SITE=0 " % \ (self.tempname, self.conn_opt, globals.timeout) if parsed_url.port is not None and parsed_url.port != 21: self.flags += u" -P '%s'" % (parsed_url.port)
def _delete_list(self, filename_list): delete_list = filename_list dont_delete_list = [] for file in self._list(): if file in delete_list: delete_list.remove(file) else: dont_delete_list.append(file) dir = tempfile.mkdtemp() # pylint: disable=redefined-builtin exclude, exclude_name = tempdir.default().mkstemp_file() to_delete = [exclude_name] for file in dont_delete_list: file = util.fsdecode(file) path = os.path.join(dir, file) to_delete.append(path) try: f = open(path, u'w') except IsADirectoryError: print(file, file=exclude) continue print(file, file=exclude) f.close() exclude.close() commandline = (u"%s --recursive --delete --exclude-from=%s %s/ %s" % (self.cmd, exclude_name, dir, self.url_string)) self.subprocess_popen(commandline) for file in to_delete: try: util.ignore_missing(os.unlink, file) except IsADirectoryError: pass os.rmdir(dir)
def patch_seq2ropath(patch_seq): """Apply the patches in patch_seq, return single ropath""" first = patch_seq[0] assert first.difftype != "diff", "First patch in sequence " \ "%s was a diff" % patch_seq if not first.isreg(): # No need to bother with data if not regular file assert len(patch_seq) == 1, "Patch sequence isn't regular, but " \ "has %d entries" % len(patch_seq) return first.get_ropath() current_file = first.open("rb") for delta_ropath in patch_seq[1:]: assert delta_ropath.difftype == "diff", delta_ropath.difftype if not isinstance(current_file, file): """ librsync insists on a real file object, which we create manually by using the duplicity.tempdir to tell us where. See https://bugs.launchpad.net/duplicity/+bug/670891 for discussion of os.tmpfile() vs tempfile.TemporaryFile() w.r.t. Windows / Posix, which is worked around in librsync.PatchedFile() now. """ tempfp = tempfile.TemporaryFile(dir=tempdir.default().dir()) util.copyfileobj(current_file, tempfp) assert not current_file.close() tempfp.seek(0) current_file = tempfp current_file = librsync.PatchedFile(current_file, delta_ropath.open("rb")) result = patch_seq[-1].get_ropath() result.setfileobj(current_file) return result
def _delete_list(self, filename_list): delete_list = filename_list dont_delete_list = [] for file in self._list(): if file in delete_list: delete_list.remove(file) else: dont_delete_list.append(file) dir = tempfile.mkdtemp() exclude, exclude_name = tempdir.default().mkstemp_file() to_delete = [exclude_name] for file in dont_delete_list: path = os.path.join(dir, file) to_delete.append(path) f = open(path, 'w') print >> exclude, file f.close() exclude.close() commandline = ("%s --recursive --delete --exclude-from=%s %s/ %s" % (self.cmd, exclude_name, dir, self.url_string)) self.subprocess_popen(commandline) for file in to_delete: util.ignore_missing(os.unlink, file) os.rmdir(dir)
def __init__(self, parsed_url): duplicity.backend.Backend.__init__(self, parsed_url) # we expect an error return, so go low-level and ignore it try: p = os.popen("ncftpls -v") fout = p.read() ret = p.close() except Exception: pass # the expected error is 8 in the high-byte and some output if ret != 0x0800 or not fout: log.FatalError("NcFTP not found: Please install NcFTP version 3.1.9 or later", log.ErrorCode.ftp_ncftp_missing) # version is the second word of the first line version = fout.split('\n')[0].split()[1] if version < "3.1.9": log.FatalError("NcFTP too old: Duplicity requires NcFTP version 3.1.9," "3.2.1 or later. Version 3.2.0 will not work properly.", log.ErrorCode.ftp_ncftp_too_old) elif version == "3.2.0": log.Warn("NcFTP (ncftpput) version 3.2.0 may fail with duplicity.\n" "see: http://www.ncftpd.com/ncftp/doc/changelog.html\n" "If you have trouble, please upgrade to 3.2.1 or later", log.WarningCode.ftp_ncftp_v320) log.Notice("NcFTP version is %s" % version) self.parsed_url = parsed_url self.url_string = duplicity.backend.strip_auth_from_url(self.parsed_url) # strip ncftp+ prefix self.url_string = duplicity.backend.strip_prefix(self.url_string, 'ncftp') # This squelches the "file not found" result from ncftpls when # the ftp backend looks for a collection that does not exist. # version 3.2.2 has error code 5, 1280 is some legacy value self.popen_breaks['ncftpls'] = [5, 1280] # Use an explicit directory name. if self.url_string[-1] != '/': self.url_string += '/' self.password = self.get_password() if globals.ftp_connection == 'regular': self.conn_opt = '-E' else: self.conn_opt = '-F' self.tempfile, self.tempname = tempdir.default().mkstemp() os.write(self.tempfile, "host %s\n" % self.parsed_url.hostname) os.write(self.tempfile, "user %s\n" % self.parsed_url.username) os.write(self.tempfile, "pass %s\n" % self.password) os.close(self.tempfile) self.flags = "-f %s %s -t %s -o useCLNT=0,useHELP_SITE=0 " % \ (self.tempname, self.conn_opt, globals.timeout) if parsed_url.port is not None and parsed_url.port != 21: self.flags += " -P '%s'" % (parsed_url.port)
def patch_seq2ropath( patch_seq ): """Apply the patches in patch_seq, return single ropath""" first = patch_seq[0] assert first.difftype != "diff", "First patch in sequence " \ "%s was a diff" % patch_seq if not first.isreg(): # No need to bother with data if not regular file assert len(patch_seq) == 1, "Patch sequence isn't regular, but " \ "has %d entries" % len(patch_seq) return first.get_ropath() current_file = first.open( "rb" ) for delta_ropath in patch_seq[1:]: assert delta_ropath.difftype == "diff", delta_ropath.difftype if not isinstance( current_file, file ): """ librsync insists on a real file object, which we create manually by using the duplicity.tempdir to tell us where. """ tempfp = tempfile.TemporaryFile( dir=tempdir.default().dir() ) misc.copyfileobj( current_file, tempfp ) assert not current_file.close() tempfp.seek( 0 ) current_file = tempfp current_file = librsync.PatchedFile( current_file, delta_ropath.open( "rb" ) ) result = patch_seq[-1].get_ropath() result.setfileobj( current_file ) return result
def patch_seq2ropath(patch_seq): """Apply the patches in patch_seq, return single ropath""" first = patch_seq[0] assert first.difftype != "diff", "First patch in sequence " \ "%s was a diff" % patch_seq if not first.isreg(): # No need to bother with data if not regular file assert len(patch_seq) == 1, "Patch sequence isn't regular, but " \ "has %d entries" % len(patch_seq) return first.get_ropath() current_file = first.open("rb") for delta_ropath in patch_seq[1:]: assert delta_ropath.difftype == "diff", delta_ropath.difftype if not isinstance(current_file, file): """ librsync insists on a real file object, which we create manually by using the duplicity.tempdir to tell us where. """ tempfp = tempfile.TemporaryFile(dir=tempdir.default().dir()) misc.copyfileobj(current_file, tempfp) assert not current_file.close() tempfp.seek(0) current_file = tempfp current_file = librsync.PatchedFile(current_file, delta_ropath.open("rb")) result = patch_seq[-1].get_ropath() result.setfileobj(current_file) return result
def delete(self, filename_list): """Delete files.""" delete_list = filename_list dont_delete_list = [] for file in self.list (): if file in delete_list: delete_list.remove (file) else: dont_delete_list.append (file) if len (delete_list) > 0: raise BackendException("Files %s not found" % str (delete_list)) dir = tempfile.mkdtemp() exclude, exclude_name = tempdir.default().mkstemp_file() to_delete = [exclude_name] for file in dont_delete_list: path = os.path.join (dir, file) to_delete.append (path) f = open (path, 'w') print >>exclude, file f.close() exclude.close() commandline = ("%s --recursive --delete --exclude-from=%s %s/ %s" % (self.cmd, exclude_name, dir, self.url_string)) self.run_command(commandline) for file in to_delete: util.ignore_missing(os.unlink, file) os.rmdir (dir)
def __init__(self, parsed_url): duplicity.backend.Backend.__init__(self, parsed_url) # we expect an output try: p = os.popen("lftp --version") fout = p.read() ret = p.close() except Exception: pass # there is no output if lftp not found if not fout: log.FatalError("LFTP not found: Please install LFTP.", log.ErrorCode.ftps_lftp_missing) # version is the second word of the second part of the first line version = fout.split('\n')[0].split(' | ')[1].split()[1] log.Notice("LFTP version is %s" % version) self.parsed_url = parsed_url self.url_string = duplicity.backend.strip_auth_from_url( self.parsed_url) # Use an explicit directory name. if self.url_string[-1] != '/': self.url_string += '/' self.password = self.get_password() if globals.ftp_connection == 'regular': self.conn_opt = 'off' else: self.conn_opt = 'on' if parsed_url.port != None and parsed_url.port != 21: self.portflag = " -p '%s'" % (parsed_url.port) else: self.portflag = "" self.tempfile, self.tempname = tempdir.default().mkstemp() os.write(self.tempfile, "set ftp:ssl-allow true\n") os.write(self.tempfile, "set ftp:ssl-protect-data true\n") os.write(self.tempfile, "set ftp:ssl-protect-list true\n") os.write(self.tempfile, "set net:timeout %s\n" % globals.timeout) os.write(self.tempfile, "set net:max-retries %s\n" % globals.num_retries) os.write(self.tempfile, "set ftp:passive-mode %s\n" % self.conn_opt) os.write(self.tempfile, "open %s %s\n" % (self.portflag, self.parsed_url.hostname)) # allow .netrc auth by only setting user/pass when user was actually given if self.parsed_url.username: os.write( self.tempfile, "user %s %s\n" % (self.parsed_url.username, self.password)) os.close(self.tempfile) self.flags = "-f %s" % self.tempname
def __init__(self, parsed_url): duplicity.backend.Backend.__init__(self, parsed_url) # we expect an output try: p = os.popen("lftp --version") fout = p.read() ret = p.close() except Exception: pass # there is no output if lftp not found if not fout: log.FatalError("LFTP not found: Please install LFTP.", log.ErrorCode.ftps_lftp_missing) # version is the second word of the second part of the first line version = fout.split('\n')[0].split(' | ')[1].split()[1] log.Notice("LFTP version is %s" % version) self.parsed_url = parsed_url self.url_string = duplicity.backend.strip_auth_from_url(self.parsed_url) # Use an explicit directory name. if self.url_string[-1] != '/': self.url_string += '/' self.password = self.get_password() if globals.ftp_connection == 'regular': self.conn_opt = 'off' else: self.conn_opt = 'on' if parsed_url.port != None and parsed_url.port != 21: self.portflag = " -p '%s'" % (parsed_url.port) else: self.portflag = "" self.tempfile, self.tempname = tempdir.default().mkstemp() os.write(self.tempfile, "set ftp:ssl-allow true\n") os.write(self.tempfile, "set ftp:ssl-protect-data true\n") os.write(self.tempfile, "set ftp:ssl-protect-list true\n") os.write(self.tempfile, "set net:timeout %s\n" % globals.timeout) os.write(self.tempfile, "set net:max-retries %s\n" % globals.num_retries) os.write(self.tempfile, "set ftp:passive-mode %s\n" % self.conn_opt) os.write(self.tempfile, "open %s %s\n" % (self.portflag, self.parsed_url.hostname)) # allow .netrc auth by only setting user/pass when user was actually given if self.parsed_url.username: os.write(self.tempfile, "user %s %s\n" % (self.parsed_url.username, self.password)) os.close(self.tempfile) self.flags = "-f %s" % self.tempname
def test_all(self): td = tempdir.default() self.assert_(td.mktemp() != td.mktemp()) dir = td.mktemp() os.mkdir(dir) os.rmdir(dir) fd, fname = td.mkstemp() os.close(fd) os.unlink(fname) td.forget(fname) fo, fname = td.mkstemp_file() fo.close() # don't forget, leave to cleanup() td.cleanup()
def test_all(self): td = tempdir.default() # are generated temp files unique? self.assertTrue(td.mktemp() != td.mktemp()) # create and remove a temp dir dir = td.mktemp() os.mkdir(dir) os.rmdir(dir) # test mkstemp() fd, fname = td.mkstemp() os.close(fd) os.unlink(fname) td.forget(fname) # test mkstemp_file() fo, fname = td.mkstemp_file() fo.close() # don't forget, leave to cleanup() # cleanup td.cleanup()
def new_temppath(): """ Return a new TempPath """ filename = tempdir.default().mktemp() return TempPath(filename)
def __init__(self, encrypt, encrypt_path, profile): """ GPGFile initializer If recipients is set, use public key encryption and encrypt to the given keys. Otherwise, use symmetric encryption. encrypt_path is the Path of the gpg encrypted file. Right now only symmetric encryption/decryption is supported. If passphrase is false, do not set passphrase - GPG program should prompt for it. """ self.status_fp = None # used to find signature self.closed = None # set to true after file closed self.logger_fp = tempfile.TemporaryFile( dir=tempdir.default().dir() ) self.stderr_fp = tempfile.TemporaryFile( dir=tempdir.default().dir() ) self.name = encrypt_path self.byte_count = 0 # Start GPG process - copied from GnuPGInterface docstring. gnupg = gpginterface.GnuPG() gnupg.options.meta_interactive = 0 gnupg.options.extra_args.append('--no-secmem-warning') if globals.use_agent: gnupg.options.extra_args.append('--use-agent') if globals.gpg_options: for opt in globals.gpg_options.split(): gnupg.options.extra_args.append(opt) cmdlist = [] if profile.sign_key: gnupg.options.default_key = profile.sign_key cmdlist.append("--sign") # encrypt: sign key needs passphrase # decrypt: encrypt key needs passphrase # special case: allow different symmetric pass with empty sign pass if encrypt and profile.sign_key and profile.signing_passphrase: passphrase = profile.signing_passphrase else: passphrase = profile.passphrase # in case the passphrase is not set, pass an empty one to prevent # TypeError: expected a character buffer object on .write() if passphrase is None: passphrase = "" if encrypt: if profile.recipients: gnupg.options.recipients = profile.recipients cmdlist.append('--encrypt') if profile.hidden_recipients: gnupg.options.hidden_recipients = profile.hidden_recipients cmdlist.append('--encrypt') if not (profile.recipients or profile.hidden_recipients): cmdlist.append('--symmetric') # use integrity protection gnupg.options.extra_args.append('--force-mdc') # Skip the passphrase if using the agent if globals.use_agent: gnupg_fhs = ['stdin',] else: gnupg_fhs = ['stdin','passphrase'] p1 = gnupg.run(cmdlist, create_fhs=gnupg_fhs, attach_fhs={'stdout': encrypt_path.open("wb"), 'stderr': self.stderr_fp, 'logger': self.logger_fp}) if not(globals.use_agent): p1.handles['passphrase'].write(passphrase) p1.handles['passphrase'].close() self.gpg_input = p1.handles['stdin'] else: if (profile.recipients or profile.hidden_recipients) and profile.encrypt_secring: cmdlist.append('--secret-keyring') cmdlist.append(profile.encrypt_secring) self.status_fp = tempfile.TemporaryFile( dir=tempdir.default().dir() ) # Skip the passphrase if using the agent if globals.use_agent: gnupg_fhs = ['stdout',] else: gnupg_fhs = ['stdout','passphrase'] p1 = gnupg.run(['--decrypt'], create_fhs=gnupg_fhs, attach_fhs={'stdin': encrypt_path.open("rb"), 'status': self.status_fp, 'stderr': self.stderr_fp, 'logger': self.logger_fp}) if not(globals.use_agent): p1.handles['passphrase'].write(passphrase) p1.handles['passphrase'].close() self.gpg_output = p1.handles['stdout'] self.gpg_process = p1 self.encrypt = encrypt
def __init__(self, parsed_url): duplicity.backend.Backend.__init__(self, parsed_url) # we expect an output try: p = os.popen("lftp --version") fout = p.read() ret = p.close() except Exception: pass # there is no output if lftp not found if not fout: log.FatalError("LFTP not found: Please install LFTP.", log.ErrorCode.ftps_lftp_missing) # version is the second word of the second part of the first line version = fout.split('\n')[0].split(' | ')[1].split()[1] log.Notice("LFTP version is %s" % version) self.parsed_url = parsed_url self.scheme = duplicity.backend.strip_prefix(parsed_url.scheme, 'lftp').lower() self.scheme = re.sub('^webdav', 'http', self.scheme) self.url_string = self.scheme + '://' + parsed_url.hostname if parsed_url.port: self.url_string += ":%s" % parsed_url.port self.remote_path = re.sub('^/', '', parsed_url.path) # Fix up an empty remote path if len(self.remote_path) == 0: self.remote_path = '/' # Use an explicit directory name. if self.remote_path[-1] != '/': self.remote_path += '/' self.authflag = '' if self.parsed_url.username: self.username = self.parsed_url.username self.password = self.get_password() self.authflag = "-u '%s,%s'" % (self.username, self.password) if globals.ftp_connection == 'regular': self.conn_opt = 'off' else: self.conn_opt = 'on' # check for cacert file if https self.cacert_file = globals.ssl_cacert_file if self.scheme == 'https' and not globals.ssl_no_check_certificate: cacert_candidates = ["~/.duplicity/cacert.pem", "~/duplicity_cacert.pem", "/etc/duplicity/cacert.pem"] # look for a default cacert file if not self.cacert_file: for path in cacert_candidates: path = os.path.expanduser(path) if (os.path.isfile(path)): self.cacert_file = path break # save config into a reusable temp file self.tempfile, self.tempname = tempdir.default().mkstemp() os.write(self.tempfile, "set ssl:verify-certificate " + ("false" if globals.ssl_no_check_certificate else "true") + "\n") if self.cacert_file: os.write(self.tempfile, "set ssl:ca-file " + cmd_quote(self.cacert_file) + "\n") if globals.ssl_cacert_path: os.write(self.tempfile, "set ssl:ca-path " + cmd_quote(globals.ssl_cacert_path) + "\n") if self.parsed_url.scheme == 'ftps': os.write(self.tempfile, "set ftp:ssl-allow true\n") os.write(self.tempfile, "set ftp:ssl-protect-data true\n") os.write(self.tempfile, "set ftp:ssl-protect-list true\n") elif self.parsed_url.scheme == 'ftpes': os.write(self.tempfile, "set ftp:ssl-force on\n") os.write(self.tempfile, "set ftp:ssl-protect-data on\n") os.write(self.tempfile, "set ftp:ssl-protect-list on\n") else: os.write(self.tempfile, "set ftp:ssl-allow false\n") os.write(self.tempfile, "set http:use-propfind true\n") os.write(self.tempfile, "set net:timeout %s\n" % globals.timeout) os.write(self.tempfile, "set net:max-retries %s\n" % globals.num_retries) os.write(self.tempfile, "set ftp:passive-mode %s\n" % self.conn_opt) if log.getverbosity() >= log.DEBUG: os.write(self.tempfile, "debug\n") if self.parsed_url.scheme == 'ftpes': os.write(self.tempfile, "open %s %s\n" % (self.authflag, self.url_string.replace('ftpes', 'ftp'))) else: os.write(self.tempfile, "open %s %s\n" % (self.authflag, self.url_string)) os.close(self.tempfile) # print settings in debug mode if log.getverbosity() >= log.DEBUG: f = open(self.tempname, 'r') log.Debug("SETTINGS: \n" "%s" % f.read())
def delete(self): """ Forget and delete """ path.Path.delete(self) tempdir.default().forget(self.name)
def new_tempduppath(parseresults): """ Return a new TempDupPath, using settings from parseresults """ filename = tempdir.default().mktemp() return TempDupPath(filename, parseresults=parseresults)
def __init__(self, parsed_url): duplicity.backend.Backend.__init__(self, parsed_url) # we expect an output try: p = os.popen("lftp --version") fout = p.read() ret = p.close() except Exception: pass # there is no output if lftp not found if not fout: log.FatalError("LFTP not found: Please install LFTP.", log.ErrorCode.ftps_lftp_missing) # version is the second word of the second part of the first line version = fout.split('\n')[0].split(' | ')[1].split()[1] log.Notice("LFTP version is %s" % version) self.parsed_url = parsed_url # self.url_string = duplicity.backend.strip_auth_from_url(self.parsed_url) # # strip lftp+ prefix # self.url_string = duplicity.backend.strip_prefix(self.url_string, 'lftp') self.scheme = duplicity.backend.strip_prefix(parsed_url.scheme, 'lftp').lower() self.scheme = re.sub('^webdav', 'http', self.scheme) self.url_string = self.scheme + '://' + parsed_url.hostname if parsed_url.port: self.url_string += ":%s" % parsed_url.port self.remote_path = re.sub('^/', '', parsed_url.path) # Fix up an empty remote path if len(self.remote_path) == 0: self.remote_path = '/' # Use an explicit directory name. if self.remote_path[-1] != '/': self.remote_path += '/' self.authflag = '' if self.parsed_url.username: self.username = self.parsed_url.username self.password = self.get_password() self.authflag = "-u '%s,%s'" % (self.username, self.password) if globals.ftp_connection == 'regular': self.conn_opt = 'off' else: self.conn_opt = 'on' # check for cacert file if https self.cacert_file = globals.ssl_cacert_file if self.scheme == 'https' and not globals.ssl_no_check_certificate: cacert_candidates = ["~/.duplicity/cacert.pem", "~/duplicity_cacert.pem", "/etc/duplicity/cacert.pem"] # if not self.cacert_file: for path in cacert_candidates: path = os.path.expanduser(path) if (os.path.isfile(path)): self.cacert_file = path break # still no cacert file, inform user if not self.cacert_file: raise duplicity.errors.FatalBackendException("""For certificate verification a cacert database file is needed in one of these locations: %s Hints: Consult the man page, chapter 'SSL Certificate Verification'. Consider using the options --ssl-cacert-file, --ssl-no-check-certificate .""" % ", ".join(cacert_candidates)) self.tempfile, self.tempname = tempdir.default().mkstemp() os.write(self.tempfile, "set ssl:verify-certificate " + ("false" if globals.ssl_no_check_certificate else "true") + "\n") if globals.ssl_cacert_file: os.write(self.tempfile, "set ssl:ca-file '" + globals.ssl_cacert_file + "'\n") if self.parsed_url.scheme == 'ftps' or self.parsed_url.scheme == 'ftpes': os.write(self.tempfile, "set ftp:ssl-allow true\n") os.write(self.tempfile, "set ftp:ssl-protect-data true\n") os.write(self.tempfile, "set ftp:ssl-protect-list true\n") else: os.write(self.tempfile, "set ftp:ssl-allow false\n") os.write(self.tempfile, "set http:use-propfind true\n") os.write(self.tempfile, "set net:timeout %s\n" % globals.timeout) os.write(self.tempfile, "set net:max-retries %s\n" % globals.num_retries) os.write(self.tempfile, "set ftp:passive-mode %s\n" % self.conn_opt) if log.getverbosity() >= log.DEBUG: os.write(self.tempfile, "debug\n") log.Debug("Changed") os.write(self.tempfile, "open %s %s\n" % (self.authflag, self.parsed_url.hostname)) # os.write(self.tempfile, "open %s %s\n" % (self.authflag, self.url_string)) # os.write(self.tempfile, "open %s %s\n" % (self.portflag, self.parsed_url.hostname)) # allow .netrc auth by only setting user/pass when user was actually given # if self.parsed_url.username: # os.write(self.tempfile, "user %s %s\n" % (self.parsed_url.username, self.password)) os.close(self.tempfile) if log.getverbosity() >= log.DEBUG: f = open(self.tempname, 'r') log.Debug("SETTINGS: \n" "%s" % f.readlines())
def __init__(self, encrypt, encrypt_path, profile): """ GPGFile initializer If recipients is set, use public key encryption and encrypt to the given keys. Otherwise, use symmetric encryption. encrypt_path is the Path of the gpg encrypted file. Right now only symmetric encryption/decryption is supported. If passphrase is false, do not set passphrase - GPG program should prompt for it. """ self.status_fp = None # used to find signature self.closed = None # set to true after file closed self.logger_fp = tempfile.TemporaryFile(dir=tempdir.default().dir()) self.stderr_fp = tempfile.TemporaryFile(dir=tempdir.default().dir()) self.name = encrypt_path self.byte_count = 0 # Start GPG process - copied from GnuPGInterface docstring. gnupg = gpginterface.GnuPG() # overrides default gpg binary 'gpg' if globals.gpg_binary is not None: gnupg.call = globals.gpg_binary gnupg.options.meta_interactive = 0 gnupg.options.extra_args.append("--no-secmem-warning") if globals.use_agent: gnupg.options.extra_args.append("--use-agent") elif profile.gpg_major == 2: # This forces gpg2 to ignore the agent. # Necessary to enforce truly non-interactive operation. if platform.platform().startswith("Linux"): gnupg.options.extra_args.append("--pinentry-mode=loopback") if globals.gpg_options: for opt in globals.gpg_options.split(): gnupg.options.extra_args.append(opt) cmdlist = [] if profile.sign_key: gnupg.options.default_key = profile.sign_key cmdlist.append("--sign") # encrypt: sign key needs passphrase # decrypt: encrypt key needs passphrase # special case: allow different symmetric pass with empty sign pass if encrypt and profile.sign_key and profile.signing_passphrase: passphrase = profile.signing_passphrase else: passphrase = profile.passphrase # in case the passphrase is not set, pass an empty one to prevent # TypeError: expected a character buffer object on .write() if passphrase is None: passphrase = "" if encrypt: if profile.recipients: gnupg.options.recipients = profile.recipients cmdlist.append("--encrypt") if profile.hidden_recipients: gnupg.options.hidden_recipients = profile.hidden_recipients cmdlist.append("--encrypt") if not (profile.recipients or profile.hidden_recipients): cmdlist.append("--symmetric") # use integrity protection gnupg.options.extra_args.append("--force-mdc") # Skip the passphrase if using the agent if globals.use_agent: gnupg_fhs = ["stdin"] else: gnupg_fhs = ["stdin", "passphrase"] p1 = gnupg.run( cmdlist, create_fhs=gnupg_fhs, attach_fhs={"stdout": encrypt_path.open("wb"), "stderr": self.stderr_fp, "logger": self.logger_fp}, ) if not (globals.use_agent): p1.handles["passphrase"].write(passphrase) p1.handles["passphrase"].close() self.gpg_input = p1.handles["stdin"] else: if (profile.recipients or profile.hidden_recipients) and profile.encrypt_secring: cmdlist.append("--secret-keyring") cmdlist.append(profile.encrypt_secring) self.status_fp = tempfile.TemporaryFile(dir=tempdir.default().dir()) # Skip the passphrase if using the agent if globals.use_agent: gnupg_fhs = ["stdout"] else: gnupg_fhs = ["stdout", "passphrase"] p1 = gnupg.run( ["--decrypt"], create_fhs=gnupg_fhs, attach_fhs={ "stdin": encrypt_path.open("rb"), "status": self.status_fp, "stderr": self.stderr_fp, "logger": self.logger_fp, }, ) if not (globals.use_agent): p1.handles["passphrase"].write(passphrase) p1.handles["passphrase"].close() self.gpg_output = p1.handles["stdout"] self.gpg_process = p1 self.encrypt = encrypt
def new_tempduppath(parseresults): """ Return a new TempDupPath, using settings from parseresults """ filename = tempdir.default().mktemp() return TempDupPath(filename, parseresults = parseresults)
def __init__(self, encrypt, encrypt_path, profile): """ GPGFile initializer If recipients is set, use public key encryption and encrypt to the given keys. Otherwise, use symmetric encryption. encrypt_path is the Path of the gpg encrypted file. Right now only symmetric encryption/decryption is supported. If passphrase is false, do not set passphrase - GPG program should prompt for it. """ self.status_fp = None # used to find signature self.closed = None # set to true after file closed self.logger_fp = tempfile.TemporaryFile(dir=tempdir.default().dir()) self.stderr_fp = tempfile.TemporaryFile(dir=tempdir.default().dir()) self.name = encrypt_path self.byte_count = 0 # Start GPG process - copied from GnuPGInterface docstring. gnupg = gpginterface.GnuPG() gnupg.options.meta_interactive = 0 gnupg.options.extra_args.append('--no-secmem-warning') if globals.use_agent: gnupg.options.extra_args.append('--use-agent') if globals.gpg_options: for opt in globals.gpg_options.split(): gnupg.options.extra_args.append(opt) cmdlist = [] if profile.sign_key: gnupg.options.default_key = profile.sign_key cmdlist.append("--sign") # encrypt: sign key needs passphrase # decrypt: encrypt key needs passphrase # special case: allow different symmetric pass with empty sign pass if encrypt and profile.sign_key and profile.signing_passphrase: passphrase = profile.signing_passphrase else: passphrase = profile.passphrase # in case the passphrase is not set, pass an empty one to prevent # TypeError: expected a character buffer object on .write() if passphrase is None: passphrase = "" if encrypt: if profile.recipients: gnupg.options.recipients = profile.recipients cmdlist.append('--encrypt') if profile.hidden_recipients: gnupg.options.hidden_recipients = profile.hidden_recipients cmdlist.append('--encrypt') if not (profile.recipients or profile.hidden_recipients): cmdlist.append('--symmetric') # use integrity protection gnupg.options.extra_args.append('--force-mdc') # Skip the passphrase if using the agent if globals.use_agent: gnupg_fhs = [ 'stdin', ] else: gnupg_fhs = ['stdin', 'passphrase'] p1 = gnupg.run(cmdlist, create_fhs=gnupg_fhs, attach_fhs={ 'stdout': encrypt_path.open("wb"), 'stderr': self.stderr_fp, 'logger': self.logger_fp }) if not (globals.use_agent): p1.handles['passphrase'].write(passphrase) p1.handles['passphrase'].close() self.gpg_input = p1.handles['stdin'] else: if (profile.recipients or profile.hidden_recipients) and profile.encrypt_secring: cmdlist.append('--secret-keyring') cmdlist.append(profile.encrypt_secring) self.status_fp = tempfile.TemporaryFile( dir=tempdir.default().dir()) # Skip the passphrase if using the agent if globals.use_agent: gnupg_fhs = [ 'stdout', ] else: gnupg_fhs = ['stdout', 'passphrase'] p1 = gnupg.run( ['--decrypt'], create_fhs=gnupg_fhs, attach_fhs={ 'stdin': encrypt_path.open("rb"), 'status': self.status_fp, 'stderr': self.stderr_fp, 'logger': self.logger_fp }) if not (globals.use_agent): p1.handles['passphrase'].write(passphrase) p1.handles['passphrase'].close() self.gpg_output = p1.handles['stdout'] self.gpg_process = p1 self.encrypt = encrypt
def __init__(self, parsed_url): duplicity.backend.Backend.__init__(self, parsed_url) # we expect an output try: p = os.popen(u"lftp --version") fout = p.read() ret = p.close() except Exception: pass # there is no output if lftp not found if not fout: log.FatalError(u"LFTP not found: Please install LFTP.", log.ErrorCode.ftps_lftp_missing) # version is the second word of the second part of the first line version = fout.split(u'\n')[0].split(u' | ')[1].split()[1] log.Notice(u"LFTP version is %s" % version) self.parsed_url = parsed_url self.scheme = duplicity.backend.strip_prefix(parsed_url.scheme, u'lftp').lower() self.scheme = re.sub(u'^webdav', u'http', self.scheme) self.url_string = self.scheme + u'://' + parsed_url.hostname if parsed_url.port: self.url_string += u":%s" % parsed_url.port self.remote_path = re.sub(u'^/', u'', parsed_url.path) # Fix up an empty remote path if len(self.remote_path) == 0: self.remote_path = u'/' # Use an explicit directory name. if self.remote_path[-1] != u'/': self.remote_path += u'/' self.authflag = u'' if self.parsed_url.username: self.username = self.parsed_url.username self.password = self.get_password() self.authflag = u"-u '%s,%s'" % (self.username, self.password) if globals.ftp_connection == u'regular': self.conn_opt = u'off' else: self.conn_opt = u'on' # check for cacert file if https self.cacert_file = globals.ssl_cacert_file if self.scheme == u'https' and not globals.ssl_no_check_certificate: cacert_candidates = [ u"~/.duplicity/cacert.pem", u"~/duplicity_cacert.pem", u"/etc/duplicity/cacert.pem" ] # look for a default cacert file if not self.cacert_file: for path in cacert_candidates: path = os.path.expanduser(path) if (os.path.isfile(path)): self.cacert_file = path break # save config into a reusable temp file self.tempfd, self.tempname = tempdir.default().mkstemp() self.tempfile = os.fdopen(self.tempfd, u"w") self.tempfile.write(u"set ssl:verify-certificate " + ( u"false" if globals.ssl_no_check_certificate else u"true") + u"\n") if self.cacert_file: self.tempfile.write(u"set ssl:ca-file " + cmd_quote(self.cacert_file) + u"\n") if globals.ssl_cacert_path: self.tempfile.write(u"set ssl:ca-path " + cmd_quote(globals.ssl_cacert_path) + u"\n") if self.parsed_url.scheme == u'ftps': self.tempfile.write(u"set ftp:ssl-allow true\n") self.tempfile.write(u"set ftp:ssl-protect-data true\n") self.tempfile.write(u"set ftp:ssl-protect-list true\n") elif self.parsed_url.scheme == u'ftpes': self.tempfile.write(u"set ftp:ssl-force on\n") self.tempfile.write(u"set ftp:ssl-protect-data on\n") self.tempfile.write(u"set ftp:ssl-protect-list on\n") else: self.tempfile.write(u"set ftp:ssl-allow false\n") self.tempfile.write(u"set http:use-propfind true\n") self.tempfile.write(u"set net:timeout %s\n" % globals.timeout) self.tempfile.write(u"set net:max-retries %s\n" % globals.num_retries) self.tempfile.write(u"set ftp:passive-mode %s\n" % self.conn_opt) if log.getverbosity() >= log.DEBUG: self.tempfile.write(u"debug\n") if self.parsed_url.scheme == u'ftpes': self.tempfile.write( u"open %s %s\n" % (self.authflag, self.url_string.replace(u'ftpes', u'ftp'))) else: self.tempfile.write(u"open %s %s\n" % (self.authflag, self.url_string)) self.tempfile.close() # print settings in debug mode if log.getverbosity() >= log.DEBUG: f = open(self.tempname, u'r') log.Debug(u"SETTINGS: \n" u"%s" % f.read())
def __init__(self, encrypt, encrypt_path, profile): u""" GPGFile initializer If recipients is set, use public key encryption and encrypt to the given keys. Otherwise, use symmetric encryption. encrypt_path is the Path of the gpg encrypted file. Right now only symmetric encryption/decryption is supported. If passphrase is false, do not set passphrase - GPG program should prompt for it. """ self.status_fp = None # used to find signature self.closed = None # set to true after file closed self.logger_fp = tempfile.TemporaryFile(dir=tempdir.default().dir()) self.stderr_fp = tempfile.TemporaryFile(dir=tempdir.default().dir()) self.name = encrypt_path self.byte_count = 0 # Start GPG process - copied from GnuPGInterface docstring. gnupg = gpginterface.GnuPG() # overrides default gpg binary 'gpg' if config.gpg_binary is not None: gnupg.call = config.gpg_binary gnupg.options.meta_interactive = 0 gnupg.options.extra_args.append(u'--no-secmem-warning') gnupg.options.extra_args.append(u'--ignore-mdc-error') # Support three versions of gpg present 1.x, 2.0.x, 2.1.x if profile.gpg_version[:1] == (1, ): if config.use_agent: # gpg1 agent use is optional gnupg.options.extra_args.append(u'--use-agent') elif profile.gpg_version[:2] == (2, 0): pass elif profile.gpg_version[:2] >= (2, 1): if not config.use_agent: # This forces gpg2 to ignore the agent. # Necessary to enforce truly non-interactive operation. gnupg.options.extra_args.append(u'--pinentry-mode=loopback') else: raise GPGError(u"Unsupported GNUPG version, %s" % profile.gpg_version) # user supplied options if config.gpg_options: for opt in config.gpg_options.split(): gnupg.options.extra_args.append(opt) cmdlist = [] if profile.sign_key: gnupg.options.default_key = profile.sign_key cmdlist.append(u"--sign") # encrypt: sign key needs passphrase # decrypt: encrypt key needs passphrase # special case: allow different symmetric pass with empty sign pass if encrypt and profile.sign_key and profile.signing_passphrase: passphrase = profile.signing_passphrase else: passphrase = profile.passphrase # in case the passphrase is not set, pass an empty one to prevent # TypeError: expected a character buffer object on .write() if passphrase is None: passphrase = u"" if encrypt: if profile.recipients: gnupg.options.recipients = profile.recipients cmdlist.append(u'--encrypt') if profile.hidden_recipients: gnupg.options.hidden_recipients = profile.hidden_recipients cmdlist.append(u'--encrypt') if not (profile.recipients or profile.hidden_recipients): cmdlist.append(u'--symmetric') # use integrity protection gnupg.options.extra_args.append(u'--force-mdc') # Skip the passphrase if using the agent if config.use_agent: gnupg_fhs = [ u'stdin', ] else: gnupg_fhs = [u'stdin', u'passphrase'] p1 = gnupg.run(cmdlist, create_fhs=gnupg_fhs, attach_fhs={ u'stdout': encrypt_path.open(u"wb"), u'stderr': self.stderr_fp, u'logger': self.logger_fp }) if not config.use_agent: p1.handles[u'passphrase'].write(passphrase) p1.handles[u'passphrase'].close() self.gpg_input = p1.handles[u'stdin'] else: if (profile.recipients or profile.hidden_recipients) and profile.encrypt_secring: cmdlist.append(u'--secret-keyring') cmdlist.append(profile.encrypt_secring) self.status_fp = tempfile.TemporaryFile( dir=tempdir.default().dir()) # Skip the passphrase if using the agent if config.use_agent: gnupg_fhs = [ u'stdout', ] else: gnupg_fhs = [u'stdout', u'passphrase'] p1 = gnupg.run( [u'--decrypt'], create_fhs=gnupg_fhs, attach_fhs={ u'stdin': encrypt_path.open(u"rb"), u'status': self.status_fp, u'stderr': self.stderr_fp, u'logger': self.logger_fp }) if not (config.use_agent): p1.handles[u'passphrase'].write(passphrase) p1.handles[u'passphrase'].close() self.gpg_output = p1.handles[u'stdout'] self.gpg_process = p1 self.encrypt = encrypt
def __init__(self, parsed_url): duplicity.backend.Backend.__init__(self, parsed_url) # we expect an output try: p = os.popen("lftp --version") fout = p.read() ret = p.close() except Exception: pass # there is no output if lftp not found if not fout: log.FatalError("LFTP not found: Please install LFTP.", log.ErrorCode.ftps_lftp_missing) # version is the second word of the second part of the first line version = fout.split('\n')[0].split(' | ')[1].split()[1] log.Notice("LFTP version is %s" % version) self.parsed_url = parsed_url # self.url_string = duplicity.backend.strip_auth_from_url(self.parsed_url) # # strip lftp+ prefix # self.url_string = duplicity.backend.strip_prefix(self.url_string, 'lftp') self.scheme = duplicity.backend.strip_prefix(parsed_url.scheme, 'lftp').lower() self.scheme = re.sub('^webdav', 'http', self.scheme) self.url_string = self.scheme + '://' + parsed_url.hostname if parsed_url.port: self.url_string += ":%s" % parsed_url.port self.remote_path = re.sub('^/', '', parsed_url.path) # Fix up an empty remote path if len(self.remote_path) == 0: self.remote_path = '/' # Use an explicit directory name. if self.remote_path[-1] != '/': self.remote_path += '/' self.authflag = '' if self.parsed_url.username: self.username = self.parsed_url.username self.password = self.get_password() self.authflag = "-u '%s,%s'" % (self.username, self.password) if globals.ftp_connection == 'regular': self.conn_opt = 'off' else: self.conn_opt = 'on' # check for cacert file if https self.cacert_file = globals.ssl_cacert_file if self.scheme == 'https' and not globals.ssl_no_check_certificate: cacert_candidates = ["~/.duplicity/cacert.pem", "~/duplicity_cacert.pem", "/etc/duplicity/cacert.pem"] # if not self.cacert_file: for path in cacert_candidates: path = os.path.expanduser(path) if (os.path.isfile(path)): self.cacert_file = path break # still no cacert file, inform user if not self.cacert_file: raise duplicity.errors.FatalBackendException("""For certificate verification a cacert database file is needed in one of these locations: %s Hints: Consult the man page, chapter 'SSL Certificate Verification'. Consider using the options --ssl-cacert-file, --ssl-no-check-certificate .""" % ", ".join(cacert_candidates)) self.tempfile, self.tempname = tempdir.default().mkstemp() os.write(self.tempfile, "set ssl:verify-certificate " + ("false" if globals.ssl_no_check_certificate else "true") + "\n") if globals.ssl_cacert_file: os.write(self.tempfile, "set ssl:ca-file '" + globals.ssl_cacert_file + "'\n") if self.parsed_url.scheme == 'ftps': os.write(self.tempfile, "set ftp:ssl-allow true\n") os.write(self.tempfile, "set ftp:ssl-protect-data true\n") os.write(self.tempfile, "set ftp:ssl-protect-list true\n") elif self.parsed_url.scheme == 'ftpes': os.write(self.tempfile, "set ftp:ssl-force on\n") os.write(self.tempfile, "set ftp:ssl-protect-data on\n") os.write(self.tempfile, "set ftp:ssl-protect-list on\n") else: os.write(self.tempfile, "set ftp:ssl-allow false\n") os.write(self.tempfile, "set http:use-propfind true\n") os.write(self.tempfile, "set net:timeout %s\n" % globals.timeout) os.write(self.tempfile, "set net:max-retries %s\n" % globals.num_retries) os.write(self.tempfile, "set ftp:passive-mode %s\n" % self.conn_opt) if log.getverbosity() >= log.DEBUG: os.write(self.tempfile, "debug\n") if self.parsed_url.scheme == 'ftpes': os.write(self.tempfile, "open %s %s\n" % (self.authflag, self.url_string.replace('ftpes','ftp'))) else: os.write(self.tempfile, "open %s %s\n" % (self.authflag, self.url_string)) # os.write(self.tempfile, "open %s %s\n" % (self.portflag, self.parsed_url.hostname)) # allow .netrc auth by only setting user/pass when user was actually given # if self.parsed_url.username: # os.write(self.tempfile, "user %s %s\n" % (self.parsed_url.username, self.password)) os.close(self.tempfile) if log.getverbosity() >= log.DEBUG: f = open(self.tempname, 'r') log.Debug("SETTINGS: \n" "%s" % f.readlines())