[apparmor] [patch] Unify code for network and capability rules in aa-mergeprof

Christian Boltz apparmor at cboltz.de
Sun May 24 19:17:16 UTC 2015


Hello,

this patch unifies the code for network and capability rules in aa-mergeprof.

This means:

a) for capability rules:
   -  move audit and deny to a new "Qualifier" header (only displayed if
      non-empty)
   -  always display options, even if only one is available
   -  use available_buttons(), which means to add the CMD_AUDIT_* button
   -  add handling for CMD_AUDIT_* button
   -  CMD_ALLOW: only add rule_obj if the user didn't select a #include
   -  move around some code to get it in sync with network rule handling

b) for network rules
   -  move audit and deny to a new "Qualifier" header (only displayed if
      non-empty)
   -  call rule_obj.severity() (not implemented for network rules, does 
      nothing)
   -  change messages to generic 'Adding %s to profile.'
   -  move around some code to get it in sync with capability rule handling

This means that the only remaining difference is in q.headers[] and the
variables feeding it:
- capability rules show "Capability: foo"
- network rules show "Network Family: foo" and "Socket type: bar"



[ 22-mergeprof-unify-capability-and-network.diff ]

=== modified file utils/aa-mergeprof
--- utils/aa-mergeprof  2015-05-24 18:51:09.096790135 +0200
+++ utils/aa-mergeprof  2015-05-24 21:04:08.835321349 +0200
@@ -316,49 +316,45 @@
                     if apparmor.aa.is_known_rule(self.user.aa[profile][hat], ruletype, rule_obj):
                         continue
 
-                    if rule_obj.all_caps:
-                        cap_txt = 'ALL'
-                    else:
-                        cap_txt = ' '.join(rule_obj.capability)
-
-                    if rule_obj.deny:
-                        cap_txt = 'deny %s' % cap_txt
-
-                    if rule_obj.audit:
-                        cap_txt = 'audit %s' % cap_txt
-
                     default_option = 1
                     options = []
                     newincludes = apparmor.aa.match_includes(self.user.aa[profile][hat], ruletype, rule_obj)
                     q = aaui.PromptQuestion()
                     if newincludes:
-                        options += list(map(lambda inc: '#include <%s>' %inc, sorted(set(newincludes))))
+                        options += list(map(lambda inc: '#include <%s>' % inc, sorted(set(newincludes))))
 
-                    if options:
-                        options.append(rule_obj.get_clean())
-                        q.options = options
-                        q.selected = default_option - 1
+                    options.append(rule_obj.get_clean())
+                    q.options = options
+                    q.selected = default_option - 1
 
                     q.headers = [_('Profile'), apparmor.aa.combine_name(profile, hat)]
+                    qualifier = ''
+                    if rule_obj.deny:
+                        qualifier = 'deny %s' % qualifier
+
+                    if rule_obj.audit:
+                        qualifier = 'audit %s' % qualifier
+
+                    if qualifier:
+                        q.headers += [_('Qualifier'), qualifier]
+
+                    if rule_obj.all_caps:
+                        cap_txt = 'ALL'
+                    else:
+                        cap_txt = ' '.join(rule_obj.capability)
+
                     q.headers += [_('Capability'), cap_txt]
 
                     severity = rule_obj.severity(sev_db)
                     if severity != '--':
                         q.headers += [_('Severity'), severity]
 
-                    audit_toggle = 0
-
-                    q.functions = []
-                    if not rule_obj.deny:
-                        q.functions += ['CMD_ALLOW']
-                    q.functions += ['CMD_DENY', 'CMD_IGNORE_ENTRY', 'CMD_ABORT', 'CMD_FINISHED']
-
+                    q.functions = available_buttons(rule_obj)
                     q.default = q.functions[0]
 
                     done = False
                     while not done:
                         ans, selected = q.promptUser()
-                        # Ignore the log entry
                         if ans == 'CMD_IGNORE_ENTRY':
                             done = True
                             break
@@ -366,13 +362,29 @@
                         elif ans == 'CMD_FINISHED':
                             return
 
-                        if ans == 'CMD_ALLOW':
-                            selection = ''
-                            if options:
-                                selection = options[selected]
-                            match = apparmor.aa.re_match_include(selection)
-                            if match:
-                                inc = match
+                        elif ans.startswith('CMD_AUDIT'):
+                            if ans == 'CMD_AUDIT_NEW':
+                                rule_obj.audit = True
+                                rule_obj.raw_rule = None
+                            else:
+                                rule_obj.audit = False
+                                rule_obj.raw_rule = None
+
+                            q.functions = available_buttons(rule_obj)
+                            options[len(options) - 1] = rule_obj.get_clean()
+                            q.options = options
+
+                            q.headers = [_('Profile'), apparmor.aa.combine_name(profile, hat)]
+                            q.headers += [_('Capability'), cap_txt]
+
+                        elif ans == 'CMD_ALLOW':
+                            done = True
+                            apparmor.aa.changed[profile] = True
+
+                            selection = options[selected]
+
+                            inc = apparmor.aa.re_match_include(selection)
+                            if inc:
                                 deleted = apparmor.aa.delete_duplicates(self.user.aa[profile][hat], inc)
                                 self.user.aa[profile][hat]['include'][inc] = True
 
@@ -380,21 +392,19 @@
                                 if deleted:
                                     aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted)
 
-                            self.user.aa[profile][hat][ruletype].add(rule_obj)
-
-                            apparmor.aa.changed[profile] = True
+                            else:
+                                self.user.aa[profile][hat][ruletype].add(rule_obj)
 
                             aaui.UI_Info(_('Adding %s to profile.') % rule_obj.get_clean())
-                            done = True
 
                         elif ans == 'CMD_DENY':
+                            done = True
+                            apparmor.aa.changed[profile] = True
+
                             rule_obj.deny = True
                             rule_obj.raw_rule = None  # reset raw rule after manually modifying rule_obj
                             self.user.aa[profile][hat][ruletype].add(rule_obj)
-                            apparmor.aa.changed[profile] = True
-
                             aaui.UI_Info(_('Adding %s to profile.') % rule_obj.get_clean())
-                            done = True
                         else:
                             done = False
 
@@ -716,40 +726,50 @@
                 ruletype = 'network'
                 if other.aa[profile][hat].get(ruletype, False): # needed until we have proper profile initialization
                     for rule_obj in other.aa[profile][hat][ruletype].rules:
-                        # severity handling for net toggles goes here
 
                         if apparmor.aa.is_known_rule(self.user.aa[profile][hat], ruletype, rule_obj):
                             continue
 
-                        if rule_obj.all_domains:
-                            family = 'ALL'
-                        else:
-                            family = rule_obj.domain
-
-                        if rule_obj.all_type_or_protocols:
-                            sock_type = 'ALL'
-                        else:
-                            sock_type = rule_obj.type_or_protocol
-
                         default_option = 1
                         options = []
                         newincludes = apparmor.aa.match_includes(self.user.aa[profile][hat], ruletype, rule_obj)
                         q = aaui.PromptQuestion()
                         if newincludes:
-                            options += list(map(lambda s: '#include <%s>'%s, sorted(set(newincludes))))
+                            options += list(map(lambda inc: '#include <%s>' % inc, sorted(set(newincludes))))
                         if True:#options:
                             options.append(rule_obj.get_clean())
                             q.options = options
                             q.selected = default_option - 1
 
-                        audit = ''
+                        q.headers = [_('Profile'), apparmor.aa.combine_name(profile, hat)]
+
+                        qualifier = ''
+                        if rule_obj.deny:
+                            qualifier = 'deny %s' % qualifier
+
                         if rule_obj.audit:
-                            audit = 'audit '
+                            qualifier = 'audit %s' % qualifier
 
-                        q.headers = [_('Profile'), apparmor.aa.combine_name(profile, hat)]
-                        q.headers += [_('Network Family'), audit + family]
+                        if qualifier:
+                            q.headers += [_('Qualifier'), qualifier]
+
+                        if rule_obj.all_domains:
+                            family = 'ALL'
+                        else:
+                            family = rule_obj.domain
+
+                        if rule_obj.all_type_or_protocols:
+                            sock_type = 'ALL'
+                        else:
+                            sock_type = rule_obj.type_or_protocol
+
+                        q.headers += [_('Network Family'), family]
                         q.headers += [_('Socket Type'), sock_type]
 
+                        severity = rule_obj.severity(sev_db)
+                        if severity != '--':
+                            q.headers += [_('Severity'), severity]
+
                         q.functions = available_buttons(rule_obj)
                         q.default = q.functions[0]
 
@@ -763,54 +783,51 @@
                             elif ans == 'CMD_FINISHED':
                                 return
 
-                            if ans.startswith('CMD_AUDIT'):
+                            elif ans.startswith('CMD_AUDIT'):
                                 if ans == 'CMD_AUDIT_NEW':
                                     rule_obj.audit = True
                                     rule_obj.raw_rule = None
-                                    audit = 'audit '
                                 else:
                                     rule_obj.audit = False
                                     rule_obj.raw_rule = None
-                                    audit = ''
 
                                 q.functions = available_buttons(rule_obj)
                                 options[len(options) - 1] = rule_obj.get_clean()
                                 q.options = options
 
                                 q.headers = [_('Profile'), apparmor.aa.combine_name(profile, hat)]
-                                q.headers += [_('Network Family'), audit + family]
+                                q.headers += [_('Network Family'), family]
                                 q.headers += [_('Socket Type'), sock_type]
 
                             elif ans == 'CMD_ALLOW':
-                                #print(options, selected)
-                                selection = options[selected]
                                 done = True
-                                if apparmor.aa.re_match_include(selection): #re.search('#include\s+<.+>$', selection):
-                                    inc =  apparmor.aa.re_match_include(selection) #re.search('#include\s+<(.+)>$', selection).groups()[0]
+                                apparmor.aa.changed[profile] = True
+
+                                selection = options[selected]
+
+                                inc = apparmor.aa.re_match_include(selection)
+                                if inc:
                                     deleted = apparmor.aa.delete_duplicates(self.user.aa[profile][hat], inc)
 
                                     self.user.aa[profile][hat]['include'][inc] = True
 
-                                    apparmor.aa.changed[profile] = True
-
-                                    aaui.UI_Info(_('Adding %s to profile') % selection)
+                                    aaui.UI_Info(_('Adding %s to profile.') % selection)
                                     if deleted:
                                         aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted)
 
                                 else:
                                     self.user.aa[profile][hat][ruletype].add(rule_obj)
 
-                                    apparmor.aa.changed[profile] = True
-
-                                    aaui.UI_Info(_('Adding network access %(family)s %(type)s to profile.') % { 'family': family, 'type': sock_type })
+                                    aaui.UI_Info(_('Adding %s to profile.') % rule_obj.get_clean())
 
                             elif ans == 'CMD_DENY':
                                 done = True
+                                apparmor.aa.changed[profile] = True
+
                                 rule_obj.deny = True
-                                rule_obj.raw_rule = None
+                                rule_obj.raw_rule = None  # reset raw rule after manually modifying rule_obj
                                 self.user.aa[profile][hat][ruletype].add(rule_obj)
-                                apparmor.aa.changed[profile] = True
-                                aaui.UI_Info(_('Denying network access %(family)s %(type)s to profile') % { 'family': family, 'type': sock_type })
+                                aaui.UI_Info(_('Adding %s to profile.') % rule_obj.get_clean())
 
                             else:
                                 done = False




Regards,

Christian Boltz
-- 
Wenn alle immer nur ausgewogen und On Topic wären, könnte wir uns gleich
assimilieren lassen. "Widerstand ist nicht zwecklos, aber hier OT."
[Ratti auf sl-etikette]




More information about the AppArmor mailing list