Intermediate codebase update and the test cases are still broken

This commit is contained in:
Kshitij Gupta 2013-07-31 19:56:33 +05:30
parent 928e4503c6
commit 8f378e3ce2
3 changed files with 772 additions and 76 deletions

View file

@ -1,6 +1,7 @@
#5546
#6585
#382-430
#480-525
#6414-6472
# No old version logs, only 2.6 + supported
#global variable names corruption
from __future__ import with_statement
@ -9,6 +10,7 @@ import logging
import os
import re
import shutil
import stat
import subprocess
import sys
import time
@ -148,8 +150,6 @@ OPERATION_TYPES = {
'sock_shutdown': 'net'
}
ARROWS = {'A': 'UP', 'B': 'DOWN', 'C': 'RIGHT', 'D': 'LEFT'}
def on_exit():
"""Shutdowns the logger and records exit if debugging enabled"""
if DEBUGGING:
@ -164,16 +164,6 @@ def op_type(operation):
operation_type = OPERATION_TYPES.get(operation, 'unknown')
return operation_type
def getkey():
key = readkey()
if key == '\x1B':
key = readkey()
if key == '[':
key = readkey()
if(ARROWS.get(key, False)):
key = ARROWS[key]
return key
def check_for_LD_XXX(file):
"""Returns True if specified program contains references to LD_PRELOAD or
LD_LIBRARY_PATH to give the Px/Ux code better suggestions"""
@ -484,7 +474,16 @@ def delete_profile(local_prof):
if aa.get(local_prof, False):
aa.pop(local_prof)
prof_unload(local_prof)
#prof_unload(local_prof)
def confirm_and_abort():
ans = UI_YesNo(gettext('Are you sure you want to abandon this set of profile changes and exit?'), 'n')
if ans == 'y':
UI_Info(gettext('Abandoning all changes.'))
shutdown_yast()
for prof in created:
delete_profile(prof)
sys.exit(0)
def get_profile(prof_name):
profile_data = None
@ -583,7 +582,8 @@ def autodep(bin_name, pname=''):
if not bin_name and pname.startswith('/'):
bin_name = pname
if not repo_cfg and not cfg['repository'].get('url', False):
repo_cfg = read_config('repository.conf')
repo_conf = apparmor.config.Config('shell')
repo_cfg = repo_conf.read_config('repository.conf')
if not repo_cfg.get('repository', False) or repo_cfg['repository']['enabled'] == 'later':
UI_ask_to_enable_repo()
if bin_name:
@ -596,7 +596,7 @@ def autodep(bin_name, pname=''):
if not bin_full:
return None
pname = bin_full
read_inactive_profile()
read_inactive_profiles()
profile_data = get_profile(pname)
# Create a new profile if no existing profile
if not profile_data:
@ -718,7 +718,19 @@ def sync_profile():
submit_changed_profiles(changed_profiles)
if new_profiles:
submit_created_profiles(new_profiles)
def fetch_profile_by_id(url, id):
#To-Do
return None, None
def fetch_profiles_by_name(url, distro, user):
#to-Do
return None, None
def fetch_profiles_by_user(url, distro, user):
#to-Do
return None, None
def submit_created_profiles(new_profiles):
#url = cfg['repository']['url']
if new_profiles:
@ -838,23 +850,11 @@ def console_select_and_upload_profiles(title, message, profiles_up):
'information is required to upload profiles to the repository.\n' +
'These changes could not be sent.\n')
def set_profile_local_only(profs):
def set_profiles_local_only(profs):
for p in profs:
aa[profs][profs]['repo']['neversubmit'] = True
writeback_ui_feedback(profs)
write_profile_ui_feedback(profs)
def confirm_and_abort():
ans = UI_YesNo('Are you sure you want to abandon this set of profile changes and exit?', 'n')
if ans == 'y':
UI_Info('Abandoning all changes.')
shutdown_yast()
for prof in created:
delete_profile(prof)
sys.exit(0)
def confirm_and_finish():
sys.stdout.write('Finishing\n')
sys.exit(0)
def build_x_functions(default, options, exec_toggle):
ret_list = []
@ -1066,7 +1066,7 @@ def handle_children(profile, hat, root):
combinedaudit = False
## Check return Value Consistency
# Check if path matches any existing regexps in profile
cm, am , m = rematch_frag(aa[profile][hat], 'allow', exec_target)
cm, am , m = rematchfrag(aa[profile][hat], 'allow', exec_target)
if cm:
combinedmode |= cm
if am:
@ -1245,7 +1245,7 @@ def handle_children(profile, hat, root):
exec_mode = str_to_mode('ix')
elif regex_optmode.search(ans):
match = regex_optmode.search(ans).groups()[0]
exec_mode = str_to_match(match)
exec_mode = str_to_mode(match)
px_default = 'n'
px_msg = gettext('Should AppArmor sanitise the environment when\n' +
'switching profiles?\n\n' +
@ -1312,10 +1312,10 @@ def handle_children(profile, hat, root):
changed[profile] = True
if exec_mode & str_to_mode('i'):
if 'perl' in exec_target:
aa[profile][hat]['include']['abstractions/perl'] = True
elif '/bin/bash' in exec_path or '/bin/sh' in exec_path:
aa[profile][hat]['include']['abstractions/bash'] = True
#if 'perl' in exec_target:
# aa[profile][hat]['include']['abstractions/perl'] = True
#elif '/bin/bash' in exec_target or '/bin/sh' in exec_target:
# aa[profile][hat]['include']['abstractions/bash'] = True
hashbang = head(exec_target)
if hashbang.startswith('#!'):
interpreter = hashbang[2:].strip()
@ -1355,9 +1355,9 @@ def handle_children(profile, hat, root):
if ynans == 'y':
helpers[exec_target] = 'enforce'
if to_name:
autodep_base('', exec_target)
autodep('', exec_target)
else:
autodep_base(exec_target, '')
autodep(exec_target, '')
reload_base(exec_target)
elif ans.startswith('CMD_cx') or ans.startswith('CMD_cix'):
if to_name:
@ -1754,6 +1754,12 @@ def is_repo_profile(profile_data):
def get_repo_user_pass():
# To-Do
pass
def get_preferred_user(repo_url):
# To-Do
pass
def repo_is_enabled():
# To-Do
return False
def update_repo_profile(profile):
# To-Do
@ -1888,13 +1894,13 @@ def ask_the_questions():
deny_mode = 0
deny_audit = 0
fmode, famode, fm = rematch_frag(aa[profile][hat], 'allow', path)
fmode, famode, fm = rematchfrag(aa[profile][hat], 'allow', path)
if fmode:
allow_mode |= fmode
if famode:
allow_audit |= famode
cm, cam, m = rematch_frag(aa[profile][hat], 'deny', path)
cm, cam, m = rematchfrag(aa[profile][hat], 'deny', path)
if cm:
deny_mode |= cm
if cam:
@ -1958,13 +1964,7 @@ def ask_the_questions():
if aa[profile][hat][incname]:
continue
if cfg['settings']['custom_includes']:
for incn in cfg['settings']['custom_includes'].split():
if incn == incname:
include_valid = True
if valid_abstraction(incname):
include_valid = True
include_valid = valid_include(profile, incname)
if not include_valid:
continue
@ -2527,7 +2527,7 @@ def save_profiles():
else:
selected_profiles_ref = yarg['PROFILES']
for profile_name in selected_profiles_ref:
writeprofile_ui_feedback(profile_name)
write_profile_ui_feedback(profile_name)
reload_base(profile_name)
else:
@ -2552,7 +2552,7 @@ def save_profiles():
display_changes(oldprofile, newprofile)
for profile_name in changed_list:
writeprofile_ui_feedback(profile_name)
write_profile_ui_feedback(profile_name)
reload_base(profile_name)
def get_pager():
@ -2646,7 +2646,7 @@ def collapse_log():
combinedmode |= aa[profile][hat]['allow']['path'][path]
# Match path to regexps in profile
combinedmode |= rematch_frag(aa[profile][hat], 'allow', path)
combinedmode |= rematchfrag(aa[profile][hat], 'allow', path)
# Match path from includes
combinedmode |= match_prof_incs_to_path(aa[profile][hat], 'allow', path)
@ -3408,7 +3408,7 @@ def escape(escape):
return '"%s"' % escape
return escape
def write_header(profile_data, depth, name, embedded_hat, write_flags):
def write_header(prof_data, depth, name, embedded_hat, write_flags):
pre = ' ' * depth
data = []
name = quote_if_needed(name)
@ -3416,46 +3416,49 @@ def write_header(profile_data, depth, name, embedded_hat, write_flags):
if (not embedded_hat and re.search('^[^\/]|^"[^\/]', name)) or (embedded_hat and re.search('^[^^]' ,name)):
name = 'profile %s' % name
if write_flags and profile_data['flags']:
data.append('%s%s flags(%s) {' % (pre, name, profile_data['flags']))
if write_flags and prof_data['flags']:
data.append('%s%s flags(%s) {' % (pre, name, prof_data['flags']))
else:
data.append('%s%s {' % (pre, name))
return data
def write_single(profile_data, depth, allow, name, prefix, tail):
def write_single(prof_data, depth, allow, name, prefix, tail):
pre = ' ' * depth
data = []
ref, allow = set_ref_allow(profile_data, allow)
ref, allow = set_ref_allow(prof_data, allow)
if ref.get(name, False):
for key in sorted(re[name].keys()):
qkey = quote_if_needed(key)
data.append(pre + allow + prefix + qkey + tail)
data.append('%s%s%s%s%s' %(pre, allow, prefix, qkey, tail))
if ref[name].keys():
data.append('')
return data
def set_ref_allow(profile_data, allow):
if allow:
if allow == 'deny':
return profile_data[allow], 'deny '
else:
return profile_data[allow], ''
def set_allow_str(allow):
if allow == 'deny':
return 'deny '
else:
return profile_data, ''
return ''
def set_ref_allow(prof_data, allow):
if allow:
return prof_data[allow], set_allow_str(allow)
else:
return prof_data, ''
def write_pair(profile_data, depth, allow, name, prefix, sep, tail, fn):
def write_pair(prof_data, depth, allow, name, prefix, sep, tail, fn):
pre = ' ' * depth
data = []
ref, allow = set_ref_allow(profile_data, allow)
ref, allow = set_ref_allow(prof_data, allow)
if ref.get(name, False):
for key in sorted(re[name].keys()):
value = fn(ref[name][key])#eval('%s(%s)' % (fn, ref[name][key]))
data.append(pre + allow + prefix + key + sep + value)
data.append('%s%s%s%s%s%s' %(pre, allow, prefix, key, sep, value))
if ref[name].keys():
data.append('')
@ -3485,9 +3488,7 @@ def write_list_vars(prof_data, depth):
def write_cap_rules(prof_data, depth, allow):
pre = ' ' * depth
data = []
allowstr = ''
if allow == 'deny':
allowstr = 'deny'
allowstr = set_allow_str(allow)
if prof_data[allow].get('capability', False):
for cap in sorted(prof_data[allow]['capability'].keys()):
@ -3495,7 +3496,7 @@ def write_cap_rules(prof_data, depth, allow):
if prof_data[allow]['capability'][cap].get('audit', False):
audit = 'audit'
if prof_data[allow]['capability'][cap].get('set', False):
data.append(pre + audit + allowstr + 'capability,')
data.append('%s%s%scapability %s,' %(pre, audit, allowstr))
data.append('')
return data
@ -3506,3 +3507,546 @@ def write_capabilities(prof_data, depth):
data += write_cap_rules(prof_data, depth, 'allow')
return data
def write_net_rules(prof_data, depth, allow):
pre = ' ' * depth
data = []
allowstr = set_allow_str(allow)
if prof_data[allow].get('netdomain', False):
if prof_data[allow]['netdomain'].get('rule', False) == 'all':
if prof_data[allow]['netdomain']['audit'].get('all', False):
audit = 'audit '
data.append('%s%snetwork,' %(pre, audit))
else:
for fam in sorted(prof_data[allow]['netdomain']['rule'].keys()):
if prof_data[allow]['netdomain']['rule'][fam] == True:
if prof_data[allow]['netdomain']['audit'][fam]:
audit = 'audit'
data.append('%s%s%snetwork %s' % (pre, audit, allowstr, fam))
else:
for typ in sorted(prof_data[allow]['netdomain']['rule'][fam].keys()):
if prof_data[allow]['netdomain']['audit'][fam].get(typ, False):
audit = 'audit'
data.append('%s%s%snetwork %s %s,' % (pre, audit, allowstr,fam, typ))
if prof_data[allow].get('netdomain', False):
data.append('')
return data
def write_netdomain(prof_data, depth):
data = write_net_rules(prof_data, depth, 'deny')
data += write_net_rules(prof_data, depth, 'allow')
return data
def write_link_rules(prof_data, depth, allow):
pre = ' ' * depth
data = []
allowstr = set_allow_str(allow)
if prof_data[allow].get('link', False):
for path in sorted(prof_data[allow]['link'].keys()):
to_name = prof_data[allow]['link'][path]['to']
subset = ''
if prof_data[allow]['link'][path]['mode'] & AA_LINK_SUBSET:
subset = 'subset'
audit = ''
if prof_data[allow]['link'][path].get('audit', False):
audit = 'audit '
path = quote_if_needed(path)
to_name = quote_if_needed(to_name)
data.append('%s%s%slink %s%s -> %s,' %(pre, audit, allowstr, subset, path, to_name))
data.append('')
return data
def write_links(prof_data, depth):
data = write_link_rules(prof_data, depth, 'deny')
data += write_link_rules(prof_data, depth, 'allow')
return data
def write_path_rules(prof_data, depth, allow):
pre = ' ' * depth
data = []
allowstr = set_allow_str(allow)
if prof_data[allow].get('path', False):
for path in sorted(prof_data[allow]['path'].keys()):
mode = prof_data[allow]['path'][path]['mode']
audit = prof_data[allow]['path'][path]['audit']
tail = ''
if prof_data[allow]['path'][path].get('to', False):
tail = ' -> %s' % prof_data[allow]['path'][path]['to']
user, other = split_mode(mode)
user_audit, other_audit = split_mode(audit)
while user or other:
ownerstr = ''
tmpmode = 0
tmpaudit = False
if user & ~other:
# if no other mode set
ownerstr = 'owner'
tmpmode = user & ~other
tmpaudit = user_audit
user = user & ~tmpmode
else:
if user_audit & ~other_audit & user:
ownerstr = 'owner '
tmpaudit = user_audit & ~other_audit & user
tmpmode = user & tmpaudit
user = user & ~tmpmode
else:
ownerstr = ''
tmpmode = user | other
tmpaudit = user_audit | other_audit
user = user & ~tmpmode
other = other & ~tmpmode
if tmpmode & tmpaudit:
modestr = mode_to_str(tmpmode & tmpaudit)
path = quote_if_needed(path)
data.append('%saudit %s%s%s %s%s,' %(pre, allowstr, ownerstr, path, modestr, tail))
tmpmode = tmpmode & ~tmpaudit
if tmpmode:
modestr = mode_to_str(tmpmode)
path = quote_if_needed(path)
data.append('%s%s%s%s %s%s,' %(pre, allowstr, ownerstr, path, modestr, tail))
data.append('')
return data
def write_paths(prof_data, depth):
data = write_path_rules(prof_data, depth, 'deny')
data += write_path_rules(prof_data, depth, 'allow')
return data
def write_rules(prof_data, depth):
data = write_alias(prof_data, depth)
data += write_list_vars(prof_data, depth)
data += write_includes(prof_data, depth)
data += write_rlimits(prof_data, depth)
data += write_capabilities(prof_data, depth)
data += write_netdomain(prof_data, depth)
data += write_links(prof_data, depth)
data += write_paths(prof_data, depth)
data += write_change_profile(prof_data, depth)
return data
def write_piece(profile_data, depth, name, nhat, write_flags):
pre = ' ' * depth
data = []
wname = None
inhat = False
if name == nhat:
wname = name
else:
wname = name + '//' + nhat
name = nhat
inhat = True
data += write_header(profile_data[name], depth, wname, False, write_flags)
data += write_rules(profile_data[name], depth+1)
pre2 = ' ' * (depth+1)
# External hat declarations
for hat in filter(lambda x: x != name, sorted(profile_data.keys())):
if profile_data[hat].get('declared', False):
data.append('%s^%s,' %(pre2, hat))
if not inhat:
# Embedded hats
for hat in filter(lambda x: x != name, sorted(profile_data.keys())):
if not profile_data[hat]['external'] and not profile_data[hat]['declared']:
data.append('')
if profile_data[hat]['profile']:
data += map(str, write_header(profile_data[hat], depth+1, hat, True, write_flags))
else:
data += map(str, write_header(profile_data[hat], depth+1, '^'+hat, True, write_flags))
data += map(str, write_rules(profile_data[hat], depth+2))
data.append('%s}' %pre2)
data.append('%s}' %pre)
# External hats
for hat in filter(lambda x: x != name, sorted(profile_data.keys())):
if name == nhat and profile_data[hat].get('external', False):
data.append('')
data += map(lambda x: ' %s' %x, write_piece(profile_data, depth-1, name, nhat, write_flags))
data.append(' }')
return data
def serialize_profile(profile_data, name, options):
string = ''
include_metadata = False
include_flags = True
data= []
if options and type(options) == dict:
if options.get('METADATA', False):
include_metadata = True
if options.get('NO_FLAGS', False):
include_flags = False
if include_metadata:
string = '# Last Modified: %s\n' %time.time()
if (profile_data[name].get('repo', False) and profile_data[name]['repo']['url']
and profile_data[name]['repo']['user'] and profile_data[name]['repo']['id']):
repo = profile_data[name]['repo']
string += '# REPOSITORY: %s %s %s\n' %(repo['url'], repo['user'], repo['id'])
elif profile_data[name]['repo']['neversubmit']:
string += '# REPOSITORY: NEVERSUBMIT\n'
if profile_data[name].get('initial_comment', False):
comment = profile_data[name]['initial_comment']
comment.replace('\\n', '\n')
string += comment + '\n'
filename = get_profile_filename(name)
if filelist.get(filename, False):
data += write_alias(filelist[filename], 0)
data += write_list_vars(filelist[filename], 0)
data += write_includes(filelist[filename], 0)
data += write_piece(profile_data, 0, name, name, include_flags)
string += '\n'.join(data)
return string+'\n'
def write_profile_ui_feedback(profile):
UI_Info(gettext('Writing updated profile for %s.') %profile)
write_profile(profile)
def write_profile(profile):
filename = None
if aa[profile][profile].get('filename', False):
filename = aa[profile][profile]['filename']
else:
filename = get_profile_filename(profile)
newprof = tempfile.NamedTemporaryFile('rw', suffix='~' ,delete=False)
if os.path.exists(filename):
shutil.copymode(filename, newprof.name)
else:
#permission_600 = stat.S_IRUSR | stat.S_IWUSR # Owner read and write
#os.chmod(newprof.name, permission_600)
pass
serialize_options = {}
serialize_options['METADATA'] = True
profile_string = serialize_profile(aa[profile], profile, serialize_options)
newprof.write(profile_string)
newprof.close()
os.rename(newprof.name, filename)
changed.pop(profile)
original_aa[profile] = deepcopy(aa[profile])
def matchliteral(aa_regexp, literal):
p_regexp = '^'+convert_regexp(aa_regexp)+'$'
match = False
try:
match = re.search(p_regexp, literal)
except:
return None
return match
def profile_known_exec(profile, typ, exec_target):
if typ == 'exec':
cm = None
am = None
m = []
cm, am, m = rematchfrag(profile, 'deny', exec_target)
if cm & AA_MAY_EXEC:
return -1
cm, am, m = match_prof_incs_to_path(profile, 'deny', exec_target)
if cm & AA_MAY_EXEC:
return -1
cm, am, m = rematchfrag(profile, 'allow', exec_target)
if cm & AA_MAY_EXEC:
return 1
cm, am, m = match_prof_incs_to_path(profile, 'allow', exec_target)
if cm & AA_MAY_EXEC:
return 1
return 0
def profile_known_capability(profile, capname):
if profile['deny']['capability'][capname].get('set', False):
return -1
if profile['allow']['capability'][capname].get('set', False):
return 1
for incname in profile['include'].keys():
if include[incname][incname]['deny']['capability'][capname].get('set', False):
return -1
if include[incname][incname]['allow']['capability'][capname].get('set', False):
return 1
return 0
def profile_known_network(profile, family, sock_type):
if netrules_access_check(profile['deny']['netdomain'], family, sock_type):
return -1
if netrules_access_check(profile['allow']['netdomain'], family, sock_type):
return 1
for incname in profile['include'].keys():
if netrules_access_check(include[incname][incname]['deny']['netdomain'], family, sock_type):
return -1
if netrules_access_check(include[incname][incname]['allow']['netdomain'], family, sock_type):
return 1
return 0
def netrules_access_check(netrules, family, sock_type):
if not netrules:
return 0
all_net = False
all_net_family = False
net_family_sock = False
if netrules['rule'].get('all', False):
all_net = True
if netrules['rule'].get(family, False) == True:
all_net_family = True
if (netrules['rule'].get(family, False) and
type(netrules['rule'][family]) == dict and
netrules['rule'][family][sock_type]):
net_family_sock = True
if all_net or all_net_family or net_family_sock:
return True
else:
return False
def reload_base(bin_path):
if not check_for_apparmor():
return None
filename = get_profile_filename(bin_path)
subprocess.call("cat '%s' | %s -I%s -r >/dev/null 2>&1" %(filename, parser ,profile_dir), shell=True)
def reload(bin_path):
bin_path = find_executable(bin_path)
if not bin:
return None
return reload_base(bin_path)
def get_include_data(filename):
data = []
if os.path.exists(profile_dir + '/' + filename):
with open_file_read(profile_dir + '/' + filename) as f_in:
data = f_in.readlines()
else:
raise AppArmorException('File Not Found: %s' %filename)
return data
def load_include(incname):
load_includeslist = [incname]
if include.get(incname, {}).get(incname, False):
return 0
while load_includeslist:
incfile = load_includeslist.pop(0)
data = get_include_data(incfile)
incdata = parse_profile_data(data, incfile, True)
if incdata:
attach_profile_data(include, incdata)
return 0
def rematchfrag(frag, allow, path):
combinedmode = 0
combinedaudit = 0
matches = []
for entry in frag[allow]['path'].keys():
match = matchliteral(entry, path)
if match:
combinedmode |= frag[allow]['path'][entry]['mode']
combinedaudit |= frag[allow]['path'][entry]['audit']
matches.append(entry)
return combinedmode, combinedaudit, matches
def match_include_to_path(incname, allow, path):
combinedmode = 0
combinedaudit = 0
matches = []
includelist = [incname]
while includelist:
incfile = includelist.pop(0)
ret = load_include(incfile)
cm, am , m = rematchfrag(include[incfile][incfile], allow, path)
if cm:
combinedmode |= cm
combinedaudit |= am
matches += m
if include[incfile][incfile][allow]['path'][path]:
combinedmode |= include[incfile][incfile][allow]['path'][path]['mode']
combinedaudit |= include[incfile][incfile][allow]['path'][path]['audit']
if include[incfile][incfile]['include'].keys():
includelist + include[incfile][incfile]['include'].keys()
return combinedmode, combinedaudit, matches
def match_prof_incs_to_path(frag, allow, path):
combinedmode = 0
combinedaudit = 0
matches = []
includelist = list(frag['include'].keys())
while includelist:
incname = includelist.pop(0)
cm, am, m = match_include_to_path(incname, allow, path)
if cm:
combinedmode |= cm
combinedaudit |= am
matches += m
return combinedmode, combinedaudit, matches
def suggest_incs_for_path(incname, path, allow):
combinedmode = 0
combinedaudit = 0
matches = []
includelist = [incname]
while includelist:
inc = includelist.pop(0)
cm, am , m = rematchfrag(include[inc][inc], 'allow', path)
if cm:
combinedmode |= cm
combinedaudit |= am
matches += m
if include[inc][inc]['allow']['path'].get(path, False):
combinedmode |= include[inc][inc]['allow']['path'][path]['mode']
combinedaudit |= include[inc][inc]['allow']['path'][path]['audit']
if include[inc][inc]['include'].keys():
includelist += include[inc][inc]['include'].keys()
return combinedmode, combinedaudit, matches
def check_qualifiers(program):
if cfg['qualifiers'].get(program, False):
if cfg['qualifiers'][program] != 'p':
fatal_error(gettext('%s is currently marked as a program that should not have its own\n' +
'profile. Usually, programs are marked this way if creating a profile for \n' +
'them is likely to break the rest of the system. If you know what you\'re\n' +
'doing and are certain you want to create a profile for this program, edit\n' +
'the corresponding entry in the [qualifiers] section in /etc/apparmor/logprof.conf.') %program)
def get_subdirectories(current_dir):
"""Returns a list of all directories directly inside given directory"""
if sys.version_info < (3,0):
return os.walk(current_dir).next()[1]
else:
return os.walk(current_dir).__next__()[1]
def loadincludes():
incdirs = get_subdirectories(profile_dir)
for idir in incdirs:
if is_skippable_dir(idir):
continue
for dirpath, dirname, files in os.walk(profile_dir + '/' + idir):
if is_skippable_dir(dirpath):
continue
for fi in files:
if is_skippable_file(fi):
continue
else:
load_include(dirpath + '/' + fi)
def glob_common(path):
globs = []
if re.search('[\d\.]+\.so$', path) or re.search('\.so\.[\d\.]+$', path):
libpath = path
libpath = re.sub('[\d\.]+\.so$', '*.so', libpath)
libpath = re.sub('\.so\.[\d\.]+$', '.so.*', libpath)
if libpath != path:
globs.append(libpath)
for glob in cfg['globs']:
if re.search(glob, path):
globbedpath = path
globbedpath = re.sub(glob, cfg['globs'][glob])
if globbedpath != path:
globs.append(globbedpath)
return sorted(set(globs))
def combine_name(name1, name2):
if name1 == name2:
return name1
else:
return '%s^%s' %(name1, name2)
def split_name(name):
names = name.split('^')
if len(names) == 1:
return name, name
else:
return names[0], names[1]
def matchregexp(new, old):
if re.search('\{.*(\,.*)*\}', old):
return None
if re.search('\[.+\]', old) or re.search('\*', old) or re.search('\?', old):
if re.search('\{.*\,.*\}', new):
pass
######Initialisations######
conf = apparmor.config.Config('ini')
cfg = conf.read_config('logprof.conf')
if cfg['settings'].get('default_owner_prompt', False):
cfg['settings']['default_owner_prompt'] = False
profile_dir = conf.find_first_dir(cfg['settings']['profiledir']) or '/etc/apparmor.d'
if not os.path.isdir(profile_dir):
raise AppArmorException('Can\'t find AppArmor profiles' )
extra_profile_dir = conf.find_first_dir(cfg['settings']['inactive_profiledir']) or '/etc/apparmor/profiles/extras/'
parser = conf.find_first_file(cfg['settings']['parser']) or '/sbin/apparmor_parser'
if not os.path.isfile(parser) or not os.access(parser, os.EX_OK):
raise AppArmorException('Can\'t find apparmor_parser')
filename = conf.find_first_file(cfg['settings']['logfiles']) or '/var/log/syslog'
if not os.path.isfile(filename):
raise AppArmorException('Can\'t find system log.')
ldd = conf.find_first_file(cfg['settings']['ldd']) or '/usr/bin/ldd'
if not os.path.isfile(ldd) or not os.access(ldd, os.EX_OK):
raise AppArmorException('Can\'t find ldd')
logger = conf.find_first_file(cfg['settings']['logger']) or '/bin/logger'
if not os.path.isfile(logger) or not os.access(logger, os.EX_OK):
raise AppArmorException('Can\'t find logger')

View file

@ -4,9 +4,10 @@ import gettext
import locale
import logging
import os
import re
from apparmor.yasti import yastLog, SendDataToYast, GetDataFromYast
from apparmor.common import readkey
from apparmor.common import readkey, AppArmorException
DEBUGGING = False
debug_logger = None
@ -30,6 +31,18 @@ def init_localisation():
trans = gettext.NullTranslations()
trans.install()
ARROWS = {'A': 'UP', 'B': 'DOWN', 'C': 'RIGHT', 'D': 'LEFT'}
def getkey():
key = readkey()
if key == '\x1B':
key = readkey()
if key == '[':
key = readkey()
if(ARROWS.get(key, False)):
key = ARROWS[key]
return key
def UI_Info(text):
if DEBUGGING:
debug_logger.info(text)
@ -71,7 +84,7 @@ def UI_YesNo(text, default):
else:
ans = default
else:
SendDataTooYast({
SendDataToYast({
'type': 'dialog-yesno',
'question': text
})
@ -130,7 +143,7 @@ def UI_GetString(text, default):
'label': text,
'default': default
})
ypath, yarg = GetDatFromYast()
ypath, yarg = GetDataFromYast()
string = yarg['string']
return string
@ -257,10 +270,149 @@ def UI_ShortMessage(title, message):
})
ypath, yarg = GetDataFromYast()
def UI_longMessage(title, message):
def UI_LongMessage(title, message):
SendDataToYast({
'type': 'long-dialog-message',
'headline': title,
'message': message
})
ypath, yarg = GetDataFromYast()
def confirm_and_finish():
sys.stdout.stdout('FINISHING\n')
sys.exit(0)
def Text_PromptUser(question):
title = question['title']
explanation = question['explanation']
headers = question['headers']
functions = question['functions']
default = question['default']
options = question['options']
selected = question.get('selected', False) or 0
helptext = question['helptext']
if helptext:
functions.append('CMD_HELP')
menu_items = []
keys = dict()
for cmd in functions:
if not CMDS.get(cmd, False):
raise AppArmorException('PromptUser: %s %s' %(gettext('Unknown command'), cmd))
menutext = gettext(CMDS[cmd])
menuhotkey = re.search('\((\S)\)', menutext)
if not menuhotkey:
raise AppArmorException('PromptUser: %s \'%s\'' %(gettext('Invalid hotkey in'), menutext))
key = menuhotkey.groups()[0].lower()
# Duplicate hotkey
if keys.get(key, False):
raise AppArmorException('PromptUser: %s %s: %s' %(gettext('Duplicate hotkey for'), cmd, menutext))
keys[key] = cmd
if default and default == cmd:
menutext = '[%s]' %menutext
menu_items.append(menutext)
default_key = 0
if default and CMDS[default]:
defaulttext = gettext(CMDS[default])
defaulthotkey = re.search('\((\S)\)', defaulttext)
if not menuhotkey:
raise AppArmorException('PromptUser: %s \'%s\'' %(gettext('Invalid hotkey in default item'), defaulttext))
default_key = defaulthotkey.groups()[0].lower()
if keys.get(default_key, False):
raise AppArmorException('PromptUser: %s %s' %(gettext('Invalid default'), default))
widest = 0
header_copy = headers[:]
while header_copy:
header = header_copy.pop(0)
header_copy.pop(0)
if len(header) > widest:
widest = len(header)
widest += 1
formatstr = '%-' + widest + 's %s\n'
function_regexp = '^('
function_regexp += '|'.join(keys.keys())
if options:
function_regexp += '|\d'
function_regexp += ')$'
ans = 'XXXINVALIDXXX'
while not re.search(function_regexp, ans, flags=re.IGNORECASE):
prompt = '\n'
if title:
prompt += '= %s =\n\n' %title
if headers:
header_copy = headers[:]
while header_copy:
header = header_copy.pop(0)
value = header_copy.pop(0)
prompt += formatstr %(header+':', value)
prompt += '\n'
if explanation:
prompt += explanation + '\n\n'
if options:
for index, option in enumerate(options):
if selected == index:
format_option = ' [%s - %s]'
else:
format_option = ' %s - %s '
prompt += format_option %(index+1, option)
prompt += '\n'
prompt += ' / '.join(menu_items)
sys.stdout.write(prompt+'\n')
ans = readkey().lower()
if ans:
if ans == 'up':
if options and selected > 0:
selected -= 1
ans = 'XXXINVALIDXXX'
elif ans == 'down':
if options and selected < len(options)-2:
selected += 1
ans = 'XXXINVALIDXXX'
elif keys.get(ans, False) == 'CMD_HELP':
sys.stdout.write('\n%s\n' %helptext)
ans = 'XXXINVALIDXXX'
elif int(ans) == 10:
# If they hit return choose default option
ans = default_key
elif options and re.search('^\d$', ans):
ans = int(ans)
if ans > 0 and ans < len(options):
selected = ans - 1
ans = 'XXXINVALIDXXX'
if keys.get(ans, False) == 'CMD_HELP':
sys.stdout.write('\n%s\n' %helptext)
ans = 'again'
if keys.get(ans, False):
ans = keys[ans]
return ans, selected

View file

@ -1,5 +1,5 @@
import re
#import ycp
import ycp
import os
import sys
import logging