summaryrefslogtreecommitdiff
path: root/rdiff-backup/rdiff_backup/Security.py
diff options
context:
space:
mode:
Diffstat (limited to 'rdiff-backup/rdiff_backup/Security.py')
-rw-r--r--rdiff-backup/rdiff_backup/Security.py166
1 files changed, 96 insertions, 70 deletions
diff --git a/rdiff-backup/rdiff_backup/Security.py b/rdiff-backup/rdiff_backup/Security.py
index 57e3d2f..efd8f04 100644
--- a/rdiff-backup/rdiff_backup/Security.py
+++ b/rdiff-backup/rdiff_backup/Security.py
@@ -19,7 +19,7 @@
"""Functions to make sure remote requests are kosher"""
-import sys, tempfile
+import sys, tempfile, types
import Globals, Main, rpath, log
class Violation(Exception):
@@ -35,6 +35,23 @@ allowed_requests = None
# set on the server.
disallowed_server_globals = ["server", "security_level", "restrict_path"]
+# Some common file commands we may want to check to make sure they are
+# in the right directory. Any commands accessing files that could be
+# added to allowed_requests must be here. A few others have also been
+# added---this is not a intended to be a complete list of course, just
+# some support for the depreciated --restrict option when the
+# security_level is "all" so you don't accidentally step out of the
+# directory.
+#
+# The keys are files request, the value is the index of the argument
+# taking a file.
+file_requests = {'os.listdir':0, 'C.make_file_dict':0, 'os.chmod':0,
+ 'os.chown':0, 'os.remove':0, 'os.removedirs':0,
+ 'os.rename':0, 'os.renames':0, 'os.rmdir':0, 'os.unlink':0,
+ 'os.utime':0, 'os.lchown':0, 'os.link':1, 'os.symlink':1,
+ 'os.mkdir':0, 'os.lchown':0}
+
+
def initialize(action, cmdpairs):
"""Initialize allowable request list and chroot"""
global allowed_requests
@@ -109,71 +126,71 @@ def set_security_level(action, cmdpairs):
def set_allowed_requests(sec_level):
"""Set the allowed requests list using the security level"""
global allowed_requests
- if sec_level == "all": return
- allowed_requests = ["VirtualFile.readfromid", "VirtualFile.closebyid",
- "Globals.get", "Globals.is_not_None",
- "Globals.get_dict_val",
- "log.Log.open_logfile_allconn",
- "log.Log.close_logfile_allconn",
- "Log.log_to_file",
- "FilenameMapping.set_init_quote_vals_local",
- "SetConnections.add_redirected_conn",
- "RedirectedRun",
- "sys.stdout.write",
- "robust.install_signal_handlers"]
- if sec_level == "minimal": pass
- elif sec_level == "read-only" or sec_level == "update-only":
- allowed_requests.extend(
- ["C.make_file_dict",
- "rpath.ea_get",
- "rpath.acl_get",
- "rpath.setdata_local",
- "log.Log.log_to_file",
- "os.getuid",
- "os.listdir",
- "Time.setcurtime_local",
- "rpath.gzip_open_local_read",
- "rpath.open_local_read",
- "Hardlink.initialize_dictionaries",
- "user_group.uid2uname",
- "user_group.gid2gname"])
- if sec_level == "read-only":
- allowed_requests.extend(
- ["fs_abilities.get_fsabilities_readonly",
- "fs_abilities.get_fsabilities_restoresource",
- "restore.MirrorStruct.set_mirror_and_rest_times",
- "restore.MirrorStruct.initialize_rf_cache",
- "restore.MirrorStruct.close_rf_cache",
- "restore.MirrorStruct.get_diffs",
- "backup.SourceStruct.get_source_select",
- "backup.SourceStruct.set_source_select",
- "backup.SourceStruct.get_diffs"])
- elif sec_level == "update-only":
- allowed_requests.extend(
- ["log.Log.open_logfile_local", "log.Log.close_logfile_local",
- "log.ErrorLog.open", "log.ErrorLog.isopen",
- "log.ErrorLog.close",
- "backup.DestinationStruct.set_rorp_cache",
- "backup.DestinationStruct.get_sigs",
- "backup.DestinationStruct.patch_and_increment",
- "Main.backup_touch_curmirror_local",
- "Main.backup_remove_curmirror_local",
- "Globals.ITRB.increment_stat",
- "statistics.record_error",
- "log.ErrorLog.write_if_open",
- "fs_abilities.get_fsabilities_readwrite"])
+ l = ["VirtualFile.readfromid", "VirtualFile.closebyid",
+ "Globals.get", "Globals.is_not_None", "Globals.get_dict_val",
+ "log.Log.open_logfile_allconn", "log.Log.close_logfile_allconn",
+ "Log.log_to_file", "FilenameMapping.set_init_quote_vals_local",
+ "SetConnections.add_redirected_conn", "RedirectedRun",
+ "sys.stdout.write", "robust.install_signal_handlers"]
+ if (sec_level == "read-only" or sec_level == "update-only" or
+ sec_level == "all"):
+ l.extend(["C.make_file_dict", "os.listdir", "rpath.ea_get",
+ "rpath.acl_get", "rpath.setdata_local",
+ "log.Log.log_to_file", "os.getuid", "Time.setcurtime_local",
+ "rpath.gzip_open_local_read", "rpath.open_local_read",
+ "Hardlink.initialize_dictionaries", "user_group.uid2uname",
+ "user_group.gid2gname"])
+ if sec_level == "read-only" or sec_level == "all":
+ l.extend(["fs_abilities.get_fsabilities_readonly",
+ "fs_abilities.get_fsabilities_restoresource",
+ "restore.MirrorStruct.set_mirror_and_rest_times",
+ "restore.MirrorStruct.set_mirror_select",
+ "restore.MirrorStruct.initialize_rf_cache",
+ "restore.MirrorStruct.close_rf_cache",
+ "restore.MirrorStruct.get_diffs",
+ "restore.ListChangedSince",
+ "restore.ListAtTime",
+ "backup.SourceStruct.get_source_select",
+ "backup.SourceStruct.set_source_select",
+ "backup.SourceStruct.get_diffs"])
+ if sec_level == "update-only" or sec_level == "all":
+ l.extend(["log.Log.open_logfile_local", "log.Log.close_logfile_local",
+ "log.ErrorLog.open", "log.ErrorLog.isopen",
+ "log.ErrorLog.close",
+ "backup.DestinationStruct.set_rorp_cache",
+ "backup.DestinationStruct.get_sigs",
+ "backup.DestinationStruct.patch_and_increment",
+ "Main.backup_touch_curmirror_local",
+ "Main.backup_remove_curmirror_local",
+ "Globals.ITRB.increment_stat",
+ "statistics.record_error",
+ "log.ErrorLog.write_if_open",
+ "fs_abilities.get_fsabilities_readwrite"])
+ if sec_level == "all":
+ l.extend(["os.mkdir", "os.chown", "os.lchown", "os.rename",
+ "os.unlink", "os.remove", "os.chmod",
+ "backup.DestinationStruct.patch",
+ "restore.TargetStruct.get_initial_iter",
+ "restore.TargetStruct.patch",
+ "restore.TargetStruct.set_target_select",
+ "regress.Regress"])
if Globals.server:
- allowed_requests.extend(
- ["SetConnections.init_connection_remote",
- "log.Log.setverbosity",
- "log.Log.setterm_verbosity",
- "Time.setprevtime_local",
- "Globals.postset_regexp_local",
- "Globals.set_select",
- "backup.SourceStruct.set_session_info",
- "backup.DestinationStruct.set_session_info",
- "user_group.init_user_mapping",
- "user_group.init_group_mapping"])
+ l.extend(["SetConnections.init_connection_remote",
+ "log.Log.setverbosity", "log.Log.setterm_verbosity",
+ "Time.setprevtime_local", "Globals.postset_regexp_local",
+ "Globals.set_select", "backup.SourceStruct.set_session_info",
+ "backup.DestinationStruct.set_session_info",
+ "user_group.init_user_mapping",
+ "user_group.init_group_mapping"])
+ allowed_requests = {}
+ for req in l: allowed_requests[req] = None
+
+def raise_violation(request, arglist):
+ """Raise a security violation about given request"""
+ raise Violation("\nWarning Security Violation!\n"
+ "Bad request for function: %s\n"
+ "with arguments: %s\n" % (request.function_string,
+ arglist))
def vet_request(request, arglist):
"""Examine request for security violations"""
@@ -182,15 +199,14 @@ def vet_request(request, arglist):
if Globals.restrict_path:
for arg in arglist:
if isinstance(arg, rpath.RPath): vet_rpath(arg)
- if security_level == "all": return
+ if request.function_string in file_requests:
+ vet_filename(request, arglist)
+ if security_level == "override": return
if request.function_string in allowed_requests: return
if request.function_string in ("Globals.set", "Globals.set_local"):
if Globals.server and arglist[0] not in disallowed_server_globals:
return
- raise Violation("\nWarning Security Violation!\n"
- "Bad request for function: %s\n"
- "with arguments: %s\n" % (request.function_string,
- arglist))
+ raise_violation(request, arglist)
def vet_rpath(rpath):
"""Require rpath not to step outside retricted directory"""
@@ -207,3 +223,13 @@ def vet_rpath(rpath):
"Request to handle path %s\n"
"which doesn't appear to be within "
"restrict path %s.\n" % (normalized, restrict))
+
+def vet_filename(request, arglist):
+ """Check to see if file operation is within the restrict_path"""
+ i = file_requests[request.function_string]
+ if len(arglist) <= i: raise_violation(request, arglist)
+ filename = arglist[i]
+ if type(filename) is not types.StringType:
+ raise_violation(request, arglist)
+ vet_rpath(rpath.RPath(Globals.local_connection, filename))
+