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): ...@@ -509,7 +509,8 @@ def RemoveOlderThan(rootrp):
"\nIf you want to delete multiple increments in this way, " "\nIf you want to delete multiple increments in this way, "
"use the --force." % (len(times_in_secs), inc_pretty_time)) "use the --force." % (len(times_in_secs), inc_pretty_time))
Log("Deleting increment%sat times:\n%s" % if len(times_in_secs) == 1:
(len(times_in_secs) == 1 and " " or "s ", inc_pretty_time), 3) 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) Manage.delete_earlier_than(datadir, time)
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
"""Functions to make sure remote requests are kosher""" """Functions to make sure remote requests are kosher"""
import sys import sys, tempfile
import Globals, tempfile import Globals, Main
from rpath import * from rpath import *
class Violation(Exception): class Violation(Exception):
...@@ -67,6 +67,8 @@ def set_security_level(action, cmdpairs): ...@@ -67,6 +67,8 @@ def set_security_level(action, cmdpairs):
rdir = tempfile.gettempdir() rdir = tempfile.gettempdir()
elif islocal(cp1): elif islocal(cp1):
sec_level = "read-only" sec_level = "read-only"
rdir = Main.restore_get_root(RPath(Globals.local_connection,
getpath(cp1)))[0].path
else: else:
assert islocal(cp2) assert islocal(cp2)
sec_level = "all" sec_level = "all"
...@@ -89,7 +91,8 @@ def set_security_level(action, cmdpairs): ...@@ -89,7 +91,8 @@ def set_security_level(action, cmdpairs):
else: assert 0, "Unknown action %s" % action else: assert 0, "Unknown action %s" % action
Globals.security_level = sec_level 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): def set_allowed_requests(sec_level):
"""Set the allowed requests list using the security level""" """Set the allowed requests list using the security level"""
...@@ -111,7 +114,9 @@ def set_allowed_requests(sec_level): ...@@ -111,7 +114,9 @@ def set_allowed_requests(sec_level):
"Time.setcurtime_local", "Time.setcurtime_local",
"Resume.ResumeCheck", "Resume.ResumeCheck",
"HLSourceStruct.split_initial_dsiter", "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": if sec_level == "update-only":
allowed_requests. \ allowed_requests. \
extend(["Log.open_logfile_local", "Log.close_logfile_local", extend(["Log.open_logfile_local", "Log.close_logfile_local",
......
...@@ -79,6 +79,7 @@ class Restore: ...@@ -79,6 +79,7 @@ class Restore:
"""Returns increments with given base""" """Returns increments with given base"""
dirname, basename = inc_rpath.dirsplit() dirname, basename = inc_rpath.dirsplit()
parent_dir = RPath(inc_rpath.conn, dirname, ()) parent_dir = RPath(inc_rpath.conn, dirname, ())
if not parent_dir.isdir(): return [] # inc directory not created yet
index = inc_rpath.index index = inc_rpath.index
if index: if index:
......
...@@ -200,10 +200,26 @@ class RPathStatic: ...@@ -200,10 +200,26 @@ class RPathStatic:
try: return tuple(os.lstat(filename)) try: return tuple(os.lstat(filename))
except os.error: return None except os.error: return None
def make_socket(path): def make_socket_local(rpath):
"""Make a local socket at the given path""" """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 = 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) MakeStatic(RPathStatic)
...@@ -587,7 +603,7 @@ class RPath(RORPath): ...@@ -587,7 +603,7 @@ class RPath(RORPath):
def mksock(self): def mksock(self):
"""Make a socket at self.path""" """Make a socket at self.path"""
self.conn.RPathStatic.make_socket(self.path) self.conn.RPathStatic.make_socket_local(self)
self.setdata() self.setdata()
assert self.issock() assert self.issock()
...@@ -700,11 +716,23 @@ class RPath(RORPath): ...@@ -700,11 +716,23 @@ class RPath(RORPath):
"""Return open file. Supports modes "w" and "r". """Return open file. Supports modes "w" and "r".
If compress is true, data written/read will be gzip 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) if self.conn is Globals.local_connection:
else: return self.conn.open(self.path, mode) 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): def write_from_fileobj(self, fp, compress = None):
"""Reads fp and writes to self.path. Closes both when done """Reads fp and writes to self.path. Closes both when done
......
...@@ -509,7 +509,8 @@ def RemoveOlderThan(rootrp): ...@@ -509,7 +509,8 @@ def RemoveOlderThan(rootrp):
"\nIf you want to delete multiple increments in this way, " "\nIf you want to delete multiple increments in this way, "
"use the --force." % (len(times_in_secs), inc_pretty_time)) "use the --force." % (len(times_in_secs), inc_pretty_time))
Log("Deleting increment%sat times:\n%s" % if len(times_in_secs) == 1:
(len(times_in_secs) == 1 and " " or "s ", inc_pretty_time), 3) 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) Manage.delete_earlier_than(datadir, time)
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
"""Functions to make sure remote requests are kosher""" """Functions to make sure remote requests are kosher"""
import sys import sys, tempfile
import Globals, tempfile import Globals, Main
from rpath import * from rpath import *
class Violation(Exception): class Violation(Exception):
...@@ -67,6 +67,8 @@ def set_security_level(action, cmdpairs): ...@@ -67,6 +67,8 @@ def set_security_level(action, cmdpairs):
rdir = tempfile.gettempdir() rdir = tempfile.gettempdir()
elif islocal(cp1): elif islocal(cp1):
sec_level = "read-only" sec_level = "read-only"
rdir = Main.restore_get_root(RPath(Globals.local_connection,
getpath(cp1)))[0].path
else: else:
assert islocal(cp2) assert islocal(cp2)
sec_level = "all" sec_level = "all"
...@@ -89,7 +91,8 @@ def set_security_level(action, cmdpairs): ...@@ -89,7 +91,8 @@ def set_security_level(action, cmdpairs):
else: assert 0, "Unknown action %s" % action else: assert 0, "Unknown action %s" % action
Globals.security_level = sec_level 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): def set_allowed_requests(sec_level):
"""Set the allowed requests list using the security level""" """Set the allowed requests list using the security level"""
...@@ -111,7 +114,9 @@ def set_allowed_requests(sec_level): ...@@ -111,7 +114,9 @@ def set_allowed_requests(sec_level):
"Time.setcurtime_local", "Time.setcurtime_local",
"Resume.ResumeCheck", "Resume.ResumeCheck",
"HLSourceStruct.split_initial_dsiter", "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": if sec_level == "update-only":
allowed_requests. \ allowed_requests. \
extend(["Log.open_logfile_local", "Log.close_logfile_local", extend(["Log.open_logfile_local", "Log.close_logfile_local",
......
...@@ -79,6 +79,7 @@ class Restore: ...@@ -79,6 +79,7 @@ class Restore:
"""Returns increments with given base""" """Returns increments with given base"""
dirname, basename = inc_rpath.dirsplit() dirname, basename = inc_rpath.dirsplit()
parent_dir = RPath(inc_rpath.conn, dirname, ()) parent_dir = RPath(inc_rpath.conn, dirname, ())
if not parent_dir.isdir(): return [] # inc directory not created yet
index = inc_rpath.index index = inc_rpath.index
if index: if index:
......
...@@ -200,10 +200,26 @@ class RPathStatic: ...@@ -200,10 +200,26 @@ class RPathStatic:
try: return tuple(os.lstat(filename)) try: return tuple(os.lstat(filename))
except os.error: return None except os.error: return None
def make_socket(path): def make_socket_local(rpath):
"""Make a local socket at the given path""" """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 = 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) MakeStatic(RPathStatic)
...@@ -587,7 +603,7 @@ class RPath(RORPath): ...@@ -587,7 +603,7 @@ class RPath(RORPath):
def mksock(self): def mksock(self):
"""Make a socket at self.path""" """Make a socket at self.path"""
self.conn.RPathStatic.make_socket(self.path) self.conn.RPathStatic.make_socket_local(self)
self.setdata() self.setdata()
assert self.issock() assert self.issock()
...@@ -700,11 +716,23 @@ class RPath(RORPath): ...@@ -700,11 +716,23 @@ class RPath(RORPath):
"""Return open file. Supports modes "w" and "r". """Return open file. Supports modes "w" and "r".
If compress is true, data written/read will be gzip 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) if self.conn is Globals.local_connection:
else: return self.conn.open(self.path, mode) 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): def write_from_fileobj(self, fp, compress = None):
"""Reads fp and writes to self.path. Closes both when done """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