19 |
|
|
20 |
"""Functions to make sure remote requests are kosher""" |
"""Functions to make sure remote requests are kosher""" |
21 |
|
|
22 |
import sys, tempfile |
import sys, tempfile, types |
23 |
import Globals, Main, rpath, log |
import Globals, Main, rpath, log |
24 |
|
|
25 |
class Violation(Exception): |
class Violation(Exception): |
35 |
# set on the server. |
# set on the server. |
36 |
disallowed_server_globals = ["server", "security_level", "restrict_path"] |
disallowed_server_globals = ["server", "security_level", "restrict_path"] |
37 |
|
|
38 |
|
# Some common file commands we may want to check to make sure they are |
39 |
|
# in the right directory. Any commands accessing files that could be |
40 |
|
# added to allowed_requests must be here. A few others have also been |
41 |
|
# added---this is not a intended to be a complete list of course, just |
42 |
|
# some support for the depreciated --restrict option when the |
43 |
|
# security_level is "all" so you don't accidentally step out of the |
44 |
|
# directory. |
45 |
|
# |
46 |
|
# The keys are files request, the value is the index of the argument |
47 |
|
# taking a file. |
48 |
|
file_requests = {'os.listdir':0, 'C.make_file_dict':0, 'os.chmod':0, |
49 |
|
'os.chown':0, 'os.remove':0, 'os.removedirs':0, |
50 |
|
'os.rename':0, 'os.renames':0, 'os.rmdir':0, 'os.unlink':0, |
51 |
|
'os.utime':0, 'os.lchown':0, 'os.link':1, 'os.symlink':1, |
52 |
|
'os.mkdir':0, 'os.lchown':0} |
53 |
|
|
54 |
|
|
55 |
def initialize(action, cmdpairs): |
def initialize(action, cmdpairs): |
56 |
"""Initialize allowable request list and chroot""" |
"""Initialize allowable request list and chroot""" |
57 |
global allowed_requests |
global allowed_requests |
126 |
def set_allowed_requests(sec_level): |
def set_allowed_requests(sec_level): |
127 |
"""Set the allowed requests list using the security level""" |
"""Set the allowed requests list using the security level""" |
128 |
global allowed_requests |
global allowed_requests |
129 |
if sec_level == "all": return |
l = ["VirtualFile.readfromid", "VirtualFile.closebyid", |
130 |
allowed_requests = ["VirtualFile.readfromid", "VirtualFile.closebyid", |
"Globals.get", "Globals.is_not_None", "Globals.get_dict_val", |
131 |
"Globals.get", "Globals.is_not_None", |
"log.Log.open_logfile_allconn", "log.Log.close_logfile_allconn", |
132 |
"Globals.get_dict_val", |
"Log.log_to_file", "FilenameMapping.set_init_quote_vals_local", |
133 |
"log.Log.open_logfile_allconn", |
"SetConnections.add_redirected_conn", "RedirectedRun", |
134 |
"log.Log.close_logfile_allconn", |
"sys.stdout.write", "robust.install_signal_handlers"] |
135 |
"Log.log_to_file", |
if (sec_level == "read-only" or sec_level == "update-only" or |
136 |
"FilenameMapping.set_init_quote_vals_local", |
sec_level == "all"): |
137 |
"SetConnections.add_redirected_conn", |
l.extend(["C.make_file_dict", "os.listdir", "rpath.ea_get", |
138 |
"RedirectedRun", |
"rpath.acl_get", "rpath.setdata_local", |
139 |
"sys.stdout.write", |
"log.Log.log_to_file", "os.getuid", "Time.setcurtime_local", |
140 |
"robust.install_signal_handlers"] |
"rpath.gzip_open_local_read", "rpath.open_local_read", |
141 |
if sec_level == "minimal": pass |
"Hardlink.initialize_dictionaries", "user_group.uid2uname", |
142 |
elif sec_level == "read-only" or sec_level == "update-only": |
"user_group.gid2gname"]) |
143 |
allowed_requests.extend( |
if sec_level == "read-only" or sec_level == "all": |
144 |
["C.make_file_dict", |
l.extend(["fs_abilities.get_fsabilities_readonly", |
145 |
"rpath.ea_get", |
"fs_abilities.get_fsabilities_restoresource", |
146 |
"rpath.acl_get", |
"restore.MirrorStruct.set_mirror_and_rest_times", |
147 |
"rpath.setdata_local", |
"restore.MirrorStruct.set_mirror_select", |
148 |
"log.Log.log_to_file", |
"restore.MirrorStruct.initialize_rf_cache", |
149 |
"os.getuid", |
"restore.MirrorStruct.close_rf_cache", |
150 |
"os.listdir", |
"restore.MirrorStruct.get_diffs", |
151 |
"Time.setcurtime_local", |
"restore.ListChangedSince", |
152 |
"rpath.gzip_open_local_read", |
"restore.ListAtTime", |
153 |
"rpath.open_local_read", |
"backup.SourceStruct.get_source_select", |
154 |
"Hardlink.initialize_dictionaries", |
"backup.SourceStruct.set_source_select", |
155 |
"user_group.uid2uname", |
"backup.SourceStruct.get_diffs"]) |
156 |
"user_group.gid2gname"]) |
if sec_level == "update-only" or sec_level == "all": |
157 |
if sec_level == "read-only": |
l.extend(["log.Log.open_logfile_local", "log.Log.close_logfile_local", |
158 |
allowed_requests.extend( |
"log.ErrorLog.open", "log.ErrorLog.isopen", |
159 |
["fs_abilities.get_fsabilities_readonly", |
"log.ErrorLog.close", |
160 |
"fs_abilities.get_fsabilities_restoresource", |
"backup.DestinationStruct.set_rorp_cache", |
161 |
"restore.MirrorStruct.set_mirror_and_rest_times", |
"backup.DestinationStruct.get_sigs", |
162 |
"restore.MirrorStruct.initialize_rf_cache", |
"backup.DestinationStruct.patch_and_increment", |
163 |
"restore.MirrorStruct.close_rf_cache", |
"Main.backup_touch_curmirror_local", |
164 |
"restore.MirrorStruct.get_diffs", |
"Main.backup_remove_curmirror_local", |
165 |
"backup.SourceStruct.get_source_select", |
"Globals.ITRB.increment_stat", |
166 |
"backup.SourceStruct.set_source_select", |
"statistics.record_error", |
167 |
"backup.SourceStruct.get_diffs"]) |
"log.ErrorLog.write_if_open", |
168 |
elif sec_level == "update-only": |
"fs_abilities.get_fsabilities_readwrite"]) |
169 |
allowed_requests.extend( |
if sec_level == "all": |
170 |
["log.Log.open_logfile_local", "log.Log.close_logfile_local", |
l.extend(["os.mkdir", "os.chown", "os.lchown", "os.rename", |
171 |
"log.ErrorLog.open", "log.ErrorLog.isopen", |
"os.unlink", "os.remove", "os.chmod", |
172 |
"log.ErrorLog.close", |
"backup.DestinationStruct.patch", |
173 |
"backup.DestinationStruct.set_rorp_cache", |
"restore.TargetStruct.get_initial_iter", |
174 |
"backup.DestinationStruct.get_sigs", |
"restore.TargetStruct.patch", |
175 |
"backup.DestinationStruct.patch_and_increment", |
"restore.TargetStruct.set_target_select", |
176 |
"Main.backup_touch_curmirror_local", |
"regress.Regress"]) |
|
"Main.backup_remove_curmirror_local", |
|
|
"Globals.ITRB.increment_stat", |
|
|
"statistics.record_error", |
|
|
"log.ErrorLog.write_if_open", |
|
|
"fs_abilities.get_fsabilities_readwrite"]) |
|
177 |
if Globals.server: |
if Globals.server: |
178 |
allowed_requests.extend( |
l.extend(["SetConnections.init_connection_remote", |
179 |
["SetConnections.init_connection_remote", |
"log.Log.setverbosity", "log.Log.setterm_verbosity", |
180 |
"log.Log.setverbosity", |
"Time.setprevtime_local", "Globals.postset_regexp_local", |
181 |
"log.Log.setterm_verbosity", |
"Globals.set_select", "backup.SourceStruct.set_session_info", |
182 |
"Time.setprevtime_local", |
"backup.DestinationStruct.set_session_info", |
183 |
"Globals.postset_regexp_local", |
"user_group.init_user_mapping", |
184 |
"Globals.set_select", |
"user_group.init_group_mapping"]) |
185 |
"backup.SourceStruct.set_session_info", |
allowed_requests = {} |
186 |
"backup.DestinationStruct.set_session_info", |
for req in l: allowed_requests[req] = None |
187 |
"user_group.init_user_mapping", |
|
188 |
"user_group.init_group_mapping"]) |
def raise_violation(request, arglist): |
189 |
|
"""Raise a security violation about given request""" |
190 |
|
raise Violation("\nWarning Security Violation!\n" |
191 |
|
"Bad request for function: %s\n" |
192 |
|
"with arguments: %s\n" % (request.function_string, |
193 |
|
arglist)) |
194 |
|
|
195 |
def vet_request(request, arglist): |
def vet_request(request, arglist): |
196 |
"""Examine request for security violations""" |
"""Examine request for security violations""" |
199 |
if Globals.restrict_path: |
if Globals.restrict_path: |
200 |
for arg in arglist: |
for arg in arglist: |
201 |
if isinstance(arg, rpath.RPath): vet_rpath(arg) |
if isinstance(arg, rpath.RPath): vet_rpath(arg) |
202 |
if security_level == "all": return |
if request.function_string in file_requests: |
203 |
|
vet_filename(request, arglist) |
204 |
|
if security_level == "override": return |
205 |
if request.function_string in allowed_requests: return |
if request.function_string in allowed_requests: return |
206 |
if request.function_string in ("Globals.set", "Globals.set_local"): |
if request.function_string in ("Globals.set", "Globals.set_local"): |
207 |
if Globals.server and arglist[0] not in disallowed_server_globals: |
if Globals.server and arglist[0] not in disallowed_server_globals: |
208 |
return |
return |
209 |
raise Violation("\nWarning Security Violation!\n" |
raise_violation(request, arglist) |
|
"Bad request for function: %s\n" |
|
|
"with arguments: %s\n" % (request.function_string, |
|
|
arglist)) |
|
210 |
|
|
211 |
def vet_rpath(rpath): |
def vet_rpath(rpath): |
212 |
"""Require rpath not to step outside retricted directory""" |
"""Require rpath not to step outside retricted directory""" |
223 |
"Request to handle path %s\n" |
"Request to handle path %s\n" |
224 |
"which doesn't appear to be within " |
"which doesn't appear to be within " |
225 |
"restrict path %s.\n" % (normalized, restrict)) |
"restrict path %s.\n" % (normalized, restrict)) |
226 |
|
|
227 |
|
def vet_filename(request, arglist): |
228 |
|
"""Check to see if file operation is within the restrict_path""" |
229 |
|
i = file_requests[request.function_string] |
230 |
|
if len(arglist) <= i: raise_violation(request, arglist) |
231 |
|
filename = arglist[i] |
232 |
|
if type(filename) is not types.StringType: |
233 |
|
raise_violation(request, arglist) |
234 |
|
vet_rpath(rpath.RPath(Globals.local_connection, filename)) |
235 |
|
|