diff options
Diffstat (limited to 'rdiff-backup/rdiff_backup/Security.py')
-rw-r--r-- | rdiff-backup/rdiff_backup/Security.py | 166 |
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)) + |