Commit 6e38e454 authored by ben's avatar ben

Fixed the remote destination restore and no increment restore bugs.


git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup@184 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
parent cb7865e1
......@@ -509,7 +509,8 @@ def RemoveOlderThan(rootrp):
"\nIf you want to delete multiple increments in this way, "
"use the --force." % (len(times_in_secs), inc_pretty_time))
Log("Deleting increment%sat times:\n%s" %
(len(times_in_secs) == 1 and " " or "s ", inc_pretty_time), 3)
if len(times_in_secs) == 1:
Log("Deleting increment at time:\n" + inc_pretty_time, 3)
else: Log("Deleting increments at times:\n" + inc_pretty_time, 3)
Manage.delete_earlier_than(datadir, time)
......@@ -10,8 +10,8 @@
"""Functions to make sure remote requests are kosher"""
import sys
import Globals, tempfile
import sys, tempfile
import Globals, Main
from rpath import *
class Violation(Exception):
......@@ -67,6 +67,8 @@ def set_security_level(action, cmdpairs):
rdir = tempfile.gettempdir()
elif islocal(cp1):
sec_level = "read-only"
rdir = Main.restore_get_root(RPath(Globals.local_connection,
getpath(cp1)))[0].path
else:
assert islocal(cp2)
sec_level = "all"
......@@ -89,7 +91,8 @@ def set_security_level(action, cmdpairs):
else: assert 0, "Unknown action %s" % action
Globals.security_level = sec_level
Globals.restrict_path = rdir
Globals.restrict_path = RPath(Globals.local_connection,
rdir).normalize().path
def set_allowed_requests(sec_level):
"""Set the allowed requests list using the security level"""
......@@ -111,7 +114,9 @@ def set_allowed_requests(sec_level):
"Time.setcurtime_local",
"Resume.ResumeCheck",
"HLSourceStruct.split_initial_dsiter",
"HLSourceStruct.get_diffs_and_finalize"])
"HLSourceStruct.get_diffs_and_finalize",
"RPathStatic.gzip_open_local_read",
"RPathStatic.open_local_read"])
if sec_level == "update-only":
allowed_requests. \
extend(["Log.open_logfile_local", "Log.close_logfile_local",
......
......@@ -79,6 +79,7 @@ class Restore:
"""Returns increments with given base"""
dirname, basename = inc_rpath.dirsplit()
parent_dir = RPath(inc_rpath.conn, dirname, ())
if not parent_dir.isdir(): return [] # inc directory not created yet
index = inc_rpath.index
if index:
......
......@@ -200,10 +200,26 @@ class RPathStatic:
try: return tuple(os.lstat(filename))
except os.error: return None
def make_socket(path):
"""Make a local socket at the given path"""
def make_socket_local(rpath):
"""Make a local socket at the given path
This takes an rpath so that it will be checked by Security.
(Miscellaneous strings will not be.)
"""
assert rpath.conn is Globals.local_connection
s = socket.socket(socket.AF_UNIX)
s.bind(path)
s.bind(rpath.path)
def gzip_open_local_read(rpath):
"""Return open GzipFile. See security note directly above"""
assert rpath.conn is Globals.local_connection
return gzip.GzipFile(rpath.path, "rb")
def open_local_read(rpath):
"""Return open file (provided for security reasons)"""
assert rpath.conn is Globals.local_connection
return open(rpath.path, "rb")
MakeStatic(RPathStatic)
......@@ -587,7 +603,7 @@ class RPath(RORPath):
def mksock(self):
"""Make a socket at self.path"""
self.conn.RPathStatic.make_socket(self.path)
self.conn.RPathStatic.make_socket_local(self)
self.setdata()
assert self.issock()
......@@ -700,11 +716,23 @@ class RPath(RORPath):
"""Return open file. Supports modes "w" and "r".
If compress is true, data written/read will be gzip
compressed/decompressed on the fly.
compressed/decompressed on the fly. The extra complications
below are for security reasons - try to make the extent of the
risk apparent from the remote call.
"""
if compress: return self.conn.gzip.GzipFile(self.path, mode)
else: return self.conn.open(self.path, mode)
if self.conn is Globals.local_connection:
if compress: return gzip.GzipFile(self.path, mode)
else: return open(self.path, mode)
if compress:
if mode == "r" or mode == "rb":
return self.conn.RPathStatic.gzip_open_local_read(self)
else: return self.conn.gzip.GzipFile(self.path, mode)
else:
if mode == "r" or mode == "rb":
return self.conn.RPathStatic.open_local_read(self)
else: return self.conn.open(self.path, mode)
def write_from_fileobj(self, fp, compress = None):
"""Reads fp and writes to self.path. Closes both when done
......
......@@ -509,7 +509,8 @@ def RemoveOlderThan(rootrp):
"\nIf you want to delete multiple increments in this way, "
"use the --force." % (len(times_in_secs), inc_pretty_time))
Log("Deleting increment%sat times:\n%s" %
(len(times_in_secs) == 1 and " " or "s ", inc_pretty_time), 3)
if len(times_in_secs) == 1:
Log("Deleting increment at time:\n" + inc_pretty_time, 3)
else: Log("Deleting increments at times:\n" + inc_pretty_time, 3)
Manage.delete_earlier_than(datadir, time)
......@@ -10,8 +10,8 @@
"""Functions to make sure remote requests are kosher"""
import sys
import Globals, tempfile
import sys, tempfile
import Globals, Main
from rpath import *
class Violation(Exception):
......@@ -67,6 +67,8 @@ def set_security_level(action, cmdpairs):
rdir = tempfile.gettempdir()
elif islocal(cp1):
sec_level = "read-only"
rdir = Main.restore_get_root(RPath(Globals.local_connection,
getpath(cp1)))[0].path
else:
assert islocal(cp2)
sec_level = "all"
......@@ -89,7 +91,8 @@ def set_security_level(action, cmdpairs):
else: assert 0, "Unknown action %s" % action
Globals.security_level = sec_level
Globals.restrict_path = rdir
Globals.restrict_path = RPath(Globals.local_connection,
rdir).normalize().path
def set_allowed_requests(sec_level):
"""Set the allowed requests list using the security level"""
......@@ -111,7 +114,9 @@ def set_allowed_requests(sec_level):
"Time.setcurtime_local",
"Resume.ResumeCheck",
"HLSourceStruct.split_initial_dsiter",
"HLSourceStruct.get_diffs_and_finalize"])
"HLSourceStruct.get_diffs_and_finalize",
"RPathStatic.gzip_open_local_read",
"RPathStatic.open_local_read"])
if sec_level == "update-only":
allowed_requests. \
extend(["Log.open_logfile_local", "Log.close_logfile_local",
......
......@@ -79,6 +79,7 @@ class Restore:
"""Returns increments with given base"""
dirname, basename = inc_rpath.dirsplit()
parent_dir = RPath(inc_rpath.conn, dirname, ())
if not parent_dir.isdir(): return [] # inc directory not created yet
index = inc_rpath.index
if index:
......
......@@ -200,10 +200,26 @@ class RPathStatic:
try: return tuple(os.lstat(filename))
except os.error: return None
def make_socket(path):
"""Make a local socket at the given path"""
def make_socket_local(rpath):
"""Make a local socket at the given path
This takes an rpath so that it will be checked by Security.
(Miscellaneous strings will not be.)
"""
assert rpath.conn is Globals.local_connection
s = socket.socket(socket.AF_UNIX)
s.bind(path)
s.bind(rpath.path)
def gzip_open_local_read(rpath):
"""Return open GzipFile. See security note directly above"""
assert rpath.conn is Globals.local_connection
return gzip.GzipFile(rpath.path, "rb")
def open_local_read(rpath):
"""Return open file (provided for security reasons)"""
assert rpath.conn is Globals.local_connection
return open(rpath.path, "rb")
MakeStatic(RPathStatic)
......@@ -587,7 +603,7 @@ class RPath(RORPath):
def mksock(self):
"""Make a socket at self.path"""
self.conn.RPathStatic.make_socket(self.path)
self.conn.RPathStatic.make_socket_local(self)
self.setdata()
assert self.issock()
......@@ -700,11 +716,23 @@ class RPath(RORPath):
"""Return open file. Supports modes "w" and "r".
If compress is true, data written/read will be gzip
compressed/decompressed on the fly.
compressed/decompressed on the fly. The extra complications
below are for security reasons - try to make the extent of the
risk apparent from the remote call.
"""
if compress: return self.conn.gzip.GzipFile(self.path, mode)
else: return self.conn.open(self.path, mode)
if self.conn is Globals.local_connection:
if compress: return gzip.GzipFile(self.path, mode)
else: return open(self.path, mode)
if compress:
if mode == "r" or mode == "rb":
return self.conn.RPathStatic.gzip_open_local_read(self)
else: return self.conn.gzip.GzipFile(self.path, mode)
else:
if mode == "r" or mode == "rb":
return self.conn.RPathStatic.open_local_read(self)
else: return self.conn.open(self.path, mode)
def write_from_fileobj(self, fp, compress = None):
"""Reads fp and writes to self.path. Closes both when done
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment